1、IoC的理念
IoC全称为Inversion of Control,中文翻译为控制反转,同时还有一个别名叫 依赖注入DI(Dependency Injection)。大多将IoC与DI看作同等概念,也有部分观点认为 依赖注入可以看作IoC的一种实现方式。
在没有Spring的时候,当我们需要依赖某个类或服务时,一般通过new创建一个对象(或者通过ServiceLocator解决直接的依赖耦合),这些都需要主动的去获取需要的对象。
ServiceLocator是通过引入中间代理者消除对象间复杂的耦合关系,并统一管理分散的复杂耦合关系。
IoC的出现就为我们提供了更加简洁的方式,不用主动去构造对象,将“主动获取”转变为“被动接收”,下图即为IoC在整个过程中的所承担的角色
通常情况下,被注入对象会直接依赖于被依赖对象。但是在IoC的场景中,二者通过IoC Service Provider来交互,全部由IoC Service Provider统一管理。控制权由被注入对象转变为了IoC Service Provider 那里。
public class NewsProvider {
// NewsProvider 为被注入对象
// INewsListener和INewsPersister为被依赖对象
private INewsListener newsListener;
private INewsPersister newsPersister;
}
其实IoC就是这么简单!以前是需要什么自己去拿,现在是需要什么东西别人主动送过来。下图形象的说明了使用IoC模式的前后差别
2、IoC(DI)的几种依赖注入的方式
IoC模式最常用的有三种依赖注入方式,分别是构造方法注入(Constructor Injection)、setter方法注入(Setter Injection)以及接口注入(Interface Injection)。
2.1、构造方法注入
构造方法注入即 被注入对象可以通过在其构造方法中声明所依赖对象的参数列表,让IoC容器知道它所需要的依赖对象列表。由于同一个对象是不可能是被构造两次的,因此,被注入对象的构造乃至其整个生命周期,都是由IoC Service Provider来管理的。
IoC Service Provider会检查被注入对象的构造方法,取得它所需要的依赖对象列表,进而为其注入相应的对象。具体代码示例如下
public class NewsProvider {
// NewsProvider 为被注入对象
// INewsListener和INewsPersister为被依赖对象
private INewsListener newsListener;
private INewsPersister newsPersister;
public NewsProvider(INewsListener newsListener, INewsPersister newsPersister) {
this.newsListener = newsListener;
this.newsPersister = newsPersister;
}
}
构造方法注入的方式比较直观,对象被构造完成后,就进入了就绪装填,可以马上使用。
2.2、setter方法注入
对于JavaBean对象来说,通常会通过setter方法来更改相应的对象属性。所以,当前对象只要为其依赖对象所对应的属性添加setter方法,就可以通过setter方法将相应的依赖对象设置到被注入对象中。代码示例如下
public class NewsProvider {
// NewsProvider 为被注入对象
// INewsListener和INewsPersister为被依赖对象
private INewsListener newsListener;
private INewsPersister newsPersister;
public void setNewsListener(INewsListener newsListener) {
this.newsListener = newsListener;
}
public void setNewsPersister(INewsPersister newsPersister) {
this.newsPersister = newsPersister;
}
}
这样,外界就可以通过调用setNewsListener和setNewsPersister方法来注入依赖对象了。
需要注意的是,setter方法注入不像构造方法注入那样,对象构造完成后即可使用,相对而言更加宽松一些,可以在对象构造完成之后再注入。
2.3、接口注入(基本废弃)
相对前面的两种注入方式来说,接口注入会更加复杂。被注入对象如果想让IoC Service Provider为其注入依赖对象,就必须实现某个接口。这个接口提供一个方法,用来为其注入依赖对象。IoC Service Provider 最终会通过这些接口来获取被注入对象所需要的依赖对象列表。
NewsProvicer为了让IoC Service Provider 为其注入所依赖的NewsListener对象,首先需要实现一个接口 INewsListenerCallable(名称随意),这个接口会声明一个injectNewsListener方法(名称随意),重要的是该方法的参数,必须是所依赖对象的类型。这样,对应的IoC Service Provider 就可以通过这个接口方法将依赖对象注入到 被注入对象 NewsProvider 当中。代码示例如下。
public interface NewsListenerCallable {
// 声明方法
void injectNewsListener(INewsListener newsListener);
}
public class NewsProvider implements NewsListenerCallable{
private INewsListener newsListener;
@Override
public void injectNewsListener(INewsListener newsListener) {
this.newsListener = newsListener;
}
}
2.3、三种注入方式的比较
- 构造方法注入。这种注入方式的优点就是,对象在构造完成之后,就已进入就绪状态,可以马上使用。缺点就是,当依赖对象变多时,构造方法的参数列表会比较长。同时通过反射构造对象时,对相同类型的参数处理会比较困难,维护和使用上也比较麻烦。而且在Java中,构造方法无法被继承,无法设置默认值。对于非必须的依赖处理,可能还需要引入多个构造方法,维护不便。
- setter方法注入。优点就是,在描述性上会比构造方法注入要好,同时可以被继承,允许设置默认值,而且有良好的IDE支持。缺点就是对象无法在构造完成后立马进入就绪状态。
- 接口注入。从注入方式的使用上来说,接口注入是目前不提倡的一种方法,基本处于“退役状态”。因为需要被注入对象实现不必要的接口,带有侵入性。
综上,构造方法注入和setter注入因为其侵入性较弱,且易于理解和使用,所以是现在使用最多的注入方式;而接口注入由于其侵入性,已经不流行了。文章来源:https://www.toymoban.com/news/detail-409947.html
本文由博客一文多发平台 OpenWrite 发布!文章来源地址https://www.toymoban.com/news/detail-409947.html
到了这里,关于《Spring揭秘》-第二章- 学习记录的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!