Ioc全程是Inversion of Control,控制反转,别名叫做依赖注入(DependencyInjection).
Ioc的宗旨:Don't call us,we will call you.
但是我们Spring为何要用Ioc,Ioc的作用是啥,有啥独特之处呢?
Ioc实际的作用就是解除对象之间的依赖关系,解除耦合关系。
没有使用Ioc模式时候,所有需要的对象都是由自己去直接创建实例使用,而是用了Ioc模式后需要取得对象的实例直接由Ioc Servcie Provider 来进行提供,解除了对象间的耦合关系。
有了这个Ioc Service Provide 提供服务,但是它怎么知道我需要的是什么对象呢?
有3种方式可以实现通知Ioc Service Provide 来进行提供服务
- 1.构造方法注入(constuctor injection)
构造方法注入可以通过在其构造方法中声明的依赖的参数列表,让外部(Ioc容器)知道它需要哪些依赖对象,比如一下的实例,只要声明以下的构造函数,即可支持构造方法注入。
public class ServiceImple{
private IDao1 dao1;
private IDao2 dao2;
public ServiceImple(IDao1 dao1,IDao2 dao2){
this.dao1 = newdao1;
this.dao2 = newdao2;
}
}
在ServiceImple构造函数中dao1,dao2就是可以通过构造方法注入。
同一个对象不同构造2次,因此被注入的对象的构造乃至整个生命周期都是有Ioc Service Provide 进行管理。当对象以构造方法注入完成后,就进入了就绪状态,可以直接是使用。缺点是:当依赖的对象过多时候,构造方法的参数列表会很长,而通过反射去构造对象时候,对相同的类型的参数处理会比较困难,维护和使用比较麻烦。而且java中构造方法无法被继承,无法设置默认值。对于非必须的依赖处理,可能需要引入多个构造方法,而参数的数量变动可能造成维护的不方便。
- 2. setter方法注入(setter injection)
public
class
ServiceImpl {
private
IDao1
dao1
;
private
IDao2
dao2
;
public
void
setDao1(IDao1
dao1
) {
this
.
dao1
=
dao1
;
}
public
void
setDao2(IDao2
dao2
) {
this
.
dao2
=
dao2
;
}
}
这样外界就可以通过调用
setDao1,
setDao2来为
ServiceImpl对象注入所依赖的对象了。
setter方法注入虽然不能像构造方法注入那样,让对象构造完成后可以立即使用,但是相对来说宽松一些,可以对象构造完成后在注入,好比去酒吧喝酒,我坐下来后可以自由的选择喝什么酒。
- 3.接口注入(interface injection)
接口的注入没有构造方法注入和setter注入简单明了。被注入的对象若是想要Ioc Service Provider 为其注入以来对象时,就必须去实现某一个接口。这个接口提供了一个方法,用来为其注入依赖对象。Ioc Service Provider 最终通过这些接口来了解应该为被注入的对象注入什么对象。
如下实例演示了如何使用接口注入
FXNewsProvider需要依赖IFXNewsListener,在这里是使用了接口注入的方式,FXNewsProvider实现了FXNewsListenerCallable接口,这个接口中声明了一个方法injectNewsListener(),该方法的参数就是所依赖的类型。这样InjectionServiceProvider就能通过这个接口的方法将对象注入到被注入的对象FXNewsProvider中去。
接口注入的方式比较死板以及繁琐,如果被注入的对象需要注入依赖对象,需要实现某一个接口。这种接口注入的方式很少用到,因为需要强制被注入对象实现特定的接口,带有侵入性。
Ioc Service Provider 是一种可以帮助我们解耦业务对象之间依赖关系的对象绑定方式。