三种依赖注入方式,即构造方法注入(constructor injection),setter方法注入(setter injection)以及接口注入(interface injection).

构造方法注入(constructor injection)

          构造方法注入,就是被注入对象可以通过在其构造方法中声明依赖对象的参数列表,让外部(通常是IOC容器)知道它需要哪些依赖对象。
          IoC Service Provider会检查被注入对象的构造方法,取得它所需要的依赖对象列表,进而为其注入相应的对象,同一个对象是不可能被构造两次的,因此,被注入对象的构造乃至整个生命周期,应该是由IOC Service Provider来管理的。 
          构造方法注入方式比较直观,对象被构造完成后,即进入构造状态,可以马上使用。

setter方法注入(setter injection)

          对于JavaBean对象来说,通常会通过setXXX()和getXXX()方法来访问对应属性。这些setXXX()方法统称为settter方法,getXXX()就成为getter方法。通过setter方法,可以更改相应的对象属性,通过getter方法,可以获得相应属性的状态。所以,当前对象只要为其依赖对象所对应的属性添加setter方法,就可以通过setter方法将相应的依赖对象设置到被注入对象中。
         setter方法注入虽不像构造方法注入那样,让对象构造完成后即可使用,但相对来说更宽松一些,可以在对象构造完成后再注入。

接口注入(interface injection)

          相对于前两种注入方式,接口注入没有那么简单明了。被注入对象如果想要IOC Service provider为其注入依赖对象,就必须实现某个接口。这个接口提供一个方法。用来为其注入依赖对象。IOC Service Provider最终通过这些接口来了解应该为被注入对象注入什么依赖对象。
          接口注入相对于前两种注入方式,比较死板和烦琐,如果需要注入依赖对象,被注入对象就必须声明和实现另外的接口。

三种注入方式的比较

        接口注入,从注入方式的使用上来说,接口注入是现在不太提倡的一种方式。因为它强制被注入对象实现不必要的接口。带有侵入性。而构造方法和setter方法注入则不需要如此。
        构造方法注入:这种注入方式的优点就是,对象在构造完成之后,即已进入就绪状态。可以马上使用。缺点就是,当依赖对象比较多的时候,构造方法的参数列表会比较长。而通过反射构造对象的时候,对相同类型的参数的处理会比较困难,维护和使用上也比较麻烦。而且在java中,构造方法无法被继承,无法设置默认值,对于非必需的依赖处理,可能需要引入多个构造方法,而参数数量的变动可能造成维护上的不便。
构造注入可以在构造器中决定依赖关系的注入顺序,优先依赖的优先注入。
对于依赖关系不需要变化的Bean,构造注入更有用处。因为没有setter方法,所有的依赖关系全部在构造器内设定,因此,不需要担心后续的代码对依赖关系产生破坏。
依赖关系只能在构造器中设定,则只有组件的创建者才能改变组件的依赖关系。对组件的调用者而言,组件内部的依赖关系完全透明,更符合高内聚的原则。
        setter方法注入:因为方法可以命名,所以setter方法注入在描述性上要比构造方法注入好一些。另外,setter方法可以被继承,允许设置默认值,而且有良好的IDE支持。缺点就是对象无法再构造完成后马上进入就绪状态。
与传统的JavaBean的写法更相似,程序开发人员更容易理解接受,通过setter方法设定依赖关系显得更加直观,自然。
对于复杂的依赖关系,如果采用构造注入,这样做的话会导致构造器过于臃肿,使得难以阅读。Spring在创建Bean实例时,需要同时实例化其依赖的全部实例,因而导致性能下降。而使用设值注入,就能够避免这些问题 。
尤其是在某些属性可选的情况下,多参数的构造器更加笨重。
        综上,构造方法注入和setter方法注入因为其侵入性较弱,且易于理解和使用,所以是现在使用最多的注入方式,而接口注入因为侵入性较强,近年来已经不流行了。

本博客参考自王福强的《Spring揭秘》

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐