失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > Spring-IoC概念

Spring-IoC概念

时间:2023-07-16 11:04:26

相关推荐

Spring-IoC概念

IoC概述

IoC(Inverse of Controller,控制反转)是spring容器的基础,AOP以及声明式事务等功能都以此为基础。对于刚开始接触Spring的程序员来说,IoC这个重要的概念比较晦涩难懂,在此通过一个例子说明这个概念。

1. 通过实例理解IoC概念

以《墨攻》电影为例,其中有一个场景,当刘德华所饰演的墨者革离到达梁国都城下时,城上梁国守军问道:“来者何人?”刘德华回答:“墨者革离!”我们不妨通过Java语言为这个“城门叩问”的场景编写剧本,并借此理解IoC的概念,代码如下所示。

/*** 通过使用演员编排剧本*/ public class MoAttack {public void cityGateAsk() {// 演员直接侵入剧本LiuDeHua ldh = new LiuDeHua();ldh.responseAsk("墨者革离!");}}

通过代码我们会发现作为具体角色饰演者的刘德华直接侵入剧本,使剧本和演员直接耦合在一起。一个明智的编剧在剧情创作时应围绕故事的角色进行,而不应考虑角色的具体饰演者,这样才能在剧本投拍时自由的选择任何合适的演员,而非绑定在某一个人身上。通过以上分析,我们需要为该剧本的主人公革离定义一个接口,接口如下所示。

/*** 通过使用角色编排剧本*/ public class MoAttack {public void cityGateAsk() {// 引入革离角色接口GeLi geli = new LiuDeHua();// 通过接口展开剧情geli.responseAsk("墨者革离!");}}

增加GeLi角色后,该剧本的情节通过角色展开,在拍摄时角色由演员饰演。但是MoAttack却同时依赖于GeLi接口和LiuDeHua类,并没有达到我们所期盼的剧本仅依赖于角色的目的。如何让LiuDeHua和剧本无关而又完成GeLi的具体动作呢?我们可以通过导演负责剧本,角色,饰演者三者的协调。通过引入导演,使得剧本和具体饰演者解耦。

现在,让我们看看IoC的概念,IoC的字面意思是控制反转,概念包含两方面:

1. 控制:选择GeLi角色扮演者的控制权

2. 反转:控制权从《墨攻》剧本中移除,转交给导演的手中

对于软件而言,某一接口具体实现类的选择控制权从调用类中移除,转交给第三方决定,即由Spring容器借由Bean配置进行控制。因为IoC确实不够开门见山,因此业界曾进行广泛的讨论,最终软件界的泰斗级任务Martin Fowler提出了DI(Dependency Injection,依赖注入)概念用来代替IoC,即让调用类对某一接口实现类的依赖关系由第三方注入,以移除调用类对某一接口实现类的依赖。

2. IoC类型

从注入方法上来看,IoC主要可以划分为三种类型:构造函数注入,属性注入和接口注入。Spring支持构造注入以及属性注入。下面继续使用以上的例子说明三种注入方式的区别。

2.1 构造函数注入

通过调用类的构造函数,将接口实现类通过构造函数变量传入,代码如下所示。

public class MoAttack {private GeLi geli;// 注入革离具体饰演者public MoAttack(GeLi geli) {this.geli = geli;}public void cityGateAsk() {geli.responseAsk("墨者革离!");}}

MoAttack的构造函数不关心具体由谁来饰演革离这个角色,只要传入的饰演者按剧本要求完成相应的表演即可,角色的具体饰演者有导演来安排,代码如下所示。

public class Director {public void direct() {// 指定角色的饰演者GeLi geli = new LiuDeHua();// 注入具体饰演者到剧本中MoAttack moAttack = new MoAttack(geli);moAttack.cityGateAsk();}}

导演首先安排刘德华饰演革离,并将刘德华“注入”到《墨攻》剧本中,然后进行“城门叩问”剧情的演出工作。

2.2 属性注入

属性注入可以有选择的通过setter方法完成调用类所需依赖的注入,更加灵活方便,代码如下所示。

public class MoAttack {private GeLi geli;// 属性注入方法public void setGeLi(GeLi geli) {this.geli = geli;}public void cityGateAsk() {geli.responseAsk("墨者革离!");}}

代码中为geli属性提供了一个Setter方法,以便让导演在需要时注入geli的具体饰演者,如下代码所示。

public class Director {public void direct() {MoAttack moAttack = new MoAttack();// 调用属性Setter方法注入GeLi geli = new LiuDeHua();moAttack.setGeli(geli);moAttack.cityGateAsk();}}

和通过构造函数注入革离饰演者不同,在实例化MoAttack剧本时,并未指定任何饰演者,而是实例化MoAttack后,在需要革离出场时,才调用setGeli()方法注入饰演者。

2.3 接口注入

将调用类所有依赖注入的方法抽取到一个接口中,调用类通过实现该接口提供相应的注入方法。为了采取接口注入的方式,必须先声明一个ActorArrangable接口,接口如下:

public interface ActorArrangable {void injectGeli()}

MoAttack通过该接口提供具体的实现,代码如下。

public class MoAttack implements ActorArrangable{private GeLi geli;// 实现接口方法public void injectGeli(GeLi geli) {this.geli = geli;}public void cityGateAsk() {geli.responseAsk("墨者革离!");}}

Director通过ActorArrangable的injectGeli()方法完成饰演者的注入工作,代码如下。

public class Director {public void direct() {MoAttack moAttack = new MoAttack();GeLi geli = new LiuDeHua();moAttack.injectGeli(geli);moAttack.cityGateAsk();}}

由于通过接口注入需要额外声明一个接口,增加了类的数目,而且效果和属性注入并无本质区别,并不推荐这种注入方式。

3. 通过容器完成依赖属性关系的注入

虽然MoAttack和LiuDeHua实现了解耦,MoAttack无须关注角色实现类的实例化工作,但这些工作中在代码中依然存在,只是转移到Director类中。现在,通过一个第三方的容器,帮助完成类的初始化与装配工作,让开发者从这些底层实现类的实例化,依赖关系装配等工作中解脱出来,专注于更有意义的业务逻辑开发工作。

Spring就是这样的一个容器,它通过配置文件或注解描述类和类之间的依赖关系,自动完成类的初始化和依赖注入工作。当容器启动时,Spring根据配置文件的描述信息,自动实例化Bean并完成依赖关系的装配,从容器中即可返回准备就绪的Bean实例,后续可直接使用。

如果觉得《Spring-IoC概念》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。
相关阅读
Spring-IoC注解

Spring-IoC注解

2022-02-12

Spring-IOC推导

Spring-IOC推导

2024-05-28

Spring-IOC本质

Spring-IOC本质

2021-06-24

Spring-IOC是什么

Spring-IOC是什么

2019-09-05