在编程的过程中,我们通常的做法就是使用new一个依赖类再调用类实例的方法,这种方法存在的一个问题就是new的类实例不好管理,为了更好的开发效率,我们使用了依赖注入的思想来管理我们的类,依赖注入的含义就是:当某个java实例(调用者)需要另一个java实例(被调用者)时,创建被调用者的工作不再由调用者完成,而是由Spring容器来完成,然后注入调用者.
Spring的依赖注入通常两种方式:设值注入和构造注入.
设值注入
设值注入是指IoC容器使用属性的setter方法来注入被依赖的实例,这种注入方式在简单直观,因而在Spring的依赖注入中大量使用.
下面举一个使用设值注入的例子
public interface Person { //定义一个使用斧子的方法 public void useAxe(); } public interface Axe { //Axe接口里有个砍的方法 public String chop(); } public class Chinese implements Person { private Axe axe; //设值注入所需的setter方法 public void setAxe(Axe axe) { this.axe=axe; } //实现Person接口的useAxe方法 public void useAxe() { //调用axe的chop()方法。表明Person对象依赖于axe对象 System.out.println(axe.chop()); } } public class StoneAxe implements Axe { public String chop() { return "使用石斧砍柴"; } } public class BeanTest { public static void main(String[] args) throws Exception { //创建Spring容器 ApplicationContext ctx=new ClassPathXmlApplicationContext("bean.xml"); Person p=ctx.getBean("Chinese",Person.class); p.useAxe(); } }下面是Spring来配置依赖注入,为Chinese类注入StoneAxe实例.
<beans> <bean id="chinese" class="Chinese"> <property name="axe" ref="stoneAxe"/> </beans> bean id="stoneAxe" class="StoneAxe" /> </beans>
构造注入
使用构造注入的方式在构造实例时,已经为其完成了依赖关系的初始化。
对设值注入的代码进行简单的修改.
public class Chinese implements Person { private Axe axe; //构造注入所需的带参数的构造器 public Chinese(Axe axe) { this.axe=axe; } //实现Person接口的useAxe方法 public void useAxe() { //调用axe的chop()方法。表明Person对象依赖于axe对象 System.out.println(axe.chop()); } }Spring配置文件
<beans> <bean id="chinese" class="Chinese"> <constructor-arg ref="stoneAxe"/> </beans> bean id="stoneAxe" class="StoneAxe" /> </beans>
使用Spring IoC容器有3个基本的要点
1.应用程序的各组件面向接口编程,面向接口编程可以将各组件之间的耦合提升到接口层次,从而有利于项目后期 的扩展.
2.应用程度的各组件不再由程序主动产生,而是由Spring容器负责产生、并初始化
3.Spring采用配置文件或者Annotation来管理Bean的实现类、依赖关系,Spring容器则根据配置文件、反射爱创 建实例,并注入依赖关系。
对比
这两种注入方式并没有绝对的好坏,只是适应的场景不同.
设值注入有如下优点:
1.与传统的JavaBean写法相似,通过setter犯法设定依赖关系显得更加直观自然.
2.复杂的依赖关系,采用构造注入,会导致构造器过于臃肿,Spring在创建Bean实例时需要同时实例化其依赖 的全部实例,因而导致性能下降.使用设值注入,则能避免这些问题.
3.在某些属性可选的情况下,多参数的构造器更加笨重.
构造注入也有其优点:
1.构造注入可以在构造器中决定依赖关系的注入顺序,优先依赖的优先注入.
2.对于依赖关系无需变化的Bean,构造注入更有用.因为没有setter方法,所有的依赖关系全部在构造器内设 定,因此无须担心后续的代码对依赖关系产生破坏.
3.依赖关系只能在构造器中设定,则只用组件的创建者才恩呢该改变组件的依赖关系.对组件的调用者而言,组 件内部的依赖关系完全透明,更符合高内聚的原则.
建议采用以设值注入为主,构造注入为辅的注入策略.对于依赖关系无须变化的注入,尽量采用构造注入,而其他的依赖关系的注入则考虑采用设值注入.