提到spring,我们总会想到它的三大核心功能:spring的事务+AOP + IOC;小编已经在前面的博客陆续介绍了事务和AOP ,在这里小编将与大家一起分享spring IOC上的理解和认识:
提到IOC,我们会想到依赖反转,依赖注入两个名词,那么什么是反转,用一句经典的话来说:Don't call us ,we will call you ! 当我们需要依赖某个类或者某个服务,最简单有效的方法就是直接再累的构造函数中新建相应的依赖类即可;但是一定要这么麻烦吗??为什么每次用到依赖对象都要我们去主动获取呢?这就引出了IOC的依赖发转的概念,也就是说我们需要依赖某个对象的时候,不是我们主动,而是被依赖对象主动提供给我们相应的服务,而我们只是使用这个对象提供的某种服务,而丝毫不关心它是被别人送过来的还是我们主动获取的!
所以实际上,IOC为避免之前的“大费周折”,为我们提供了更加轻松简洁的方式,反转你之前的“事必躬亲”,转为现在的坐等服务,因此IOC的理念就是 让别人为你服务;也就是让IOC service provider为你服务;
在IOC场景中,被注入对象和被依赖对象通过IOC service provider 来打交道,所有被注入的对象和依赖对象会被该provider 同意管理,被注入的对象需要什么,直接跟IOC service provider 招呼一声,后者就会将相应的呗依赖对象注入到被注入对象中,从而达到IOC service provider为被注入对象服务的目的。
所以IOC就是这么简单,但是作为被注入对象,要想让IOC service provider 为其提供服务,并将所需要的被依赖对象送过来,也需要通过某种方式通知对象。主要是通过三种方式来通知:构造方法注入,setter方法注入,接口注入:
1.构造方法注入
顾名思义,构造方法注入,就是被注入对象可以通过在其构造方法中声明依赖对象的参数列表,让外部(通常是IoC容器)知道它需要哪些依赖对象。对于前面例子中的FXNewsProvider来说,只要声明如下构造方法(见代码清单2-3)即可支持构造方法注入。
public FXNewsProvider(IFXNewsListener newsListner,IFXNewsPersister newsPersister)
{
this.newsListener = newsListner;
this.newPersistener = newsPersister;
}<span style="font-family:Arial, Helvetica, sans-serif;"><span style="white-space: normal;">
</span></span>
IoC Service Provider会检查被注入对象的构造方法,取得它所需要的依赖对象列表,进而为其注入相应的对象。同一个对象是不可能被构造两次的,因此,被注入对象的构造乃至其整个生命周期,应该是由IoC Service Provider来管理的。
2. setter方法注入
对于javaBean对象来说,通常通过set()和get()方法来访问对应的属性。这些set()方法统称为setter方法。通过setter()方法可以更改相应的对象属性。所以当前对象只要为其依赖对象所对应的属性添加setter方法,就可以通过setter方法将相应的依赖对象设置到被注入对象中。
public class FXNewsProvider
{
private IFXNewsListener newsListener;
private IFXNewsPersister newPersistener;
public IFXNewsListener getNewsListener() {
return newsListener;
}
public void setNewsListener(IFXNewsListener newsListener) {
this.newsListener = newsListener;
}
public IFXNewsPersister getNewPersistener() {
return newPersistener;
}
public void setNewPersistener(IFXNewsPersister newPersistener) {
this.newPersistener = newPersistener;
}
}
这样,外界就可以通过setNewsListener和setNewPersistener方法为FXNewsProvider对象注入所依赖的对象了;
3. 接口注入
相对于前两种注入方式来说,接口注入没有那么简单明了。被注入对象如果想要IoC ServiceProvider为其注入依赖对象,就必须实现某个接口。这个接口提供一个方法,用来为其注入依赖对象。IoC Service Provider最终通过这些接口来了解应该为被注入对象注入什么依赖对象。图 2-3演示了如何使用接口注入为FXNewsProvider注入依赖对象。 FXNewsProvider为了让IoC Service Provider为其注入所依赖的IFXNewsListener,首先需要实现IFXNewsListenerCallable接口,这个接口会声明一个injectNewsListner方法(方法名随意),该方法的参数,就是所依赖对象的类型。这样, InjectionServiceContainer对象,即对应的IoCService Provider就可以通过这个接口方法将依赖对象注入到被注入对象FXNewsProvider当中。
相对于前两种依赖注入的方式,接口注入比较死板和繁琐,如果需要注入依赖对象,被注入对象就必须声明和实现另外的接口。就像是在酒吧点啤酒,为了让服务生理解你的意思,你就必须戴上一顶啤酒杯式的帽子,看起来多此一举;
总结:
1.构造方法注入:
2.setter方法注入
因为方法可以命名, 所以setter方法注入在描述性上要比构造方法注入好一些。另外, setter方法可以被继承,允许设置默认值,而且有良好的IDE支持。
缺点当然就是对象无法在构造完成后马上进入就绪状态。
3.接口注入
从注入方式的使用上来说,接口注入是现在不甚提倡的一种方式,基本处于“退役状态”。因为它强制被注入对象实现不必要的接口,带有侵入性。而构造方法注入和setter方法注入则不需要如此。
不管是哪种注入方式,都有适合自己的使用场景,也都能帮我们实现注入,但是在实际编程中使用的时候,还是需要我们仔细辨别编程环境和各个注入方式的优缺点,选择最恰当的注入方式,最大程度的发挥IOC容器给我们的便利!