Spring 的核心机制:依赖注入(控制反转)

1、说到依赖注入(控制反转),先要理解什么是依赖。

Spring 把相互协做的关系称为依赖关系。假如 A 组件调用了 B 组件的方法,咱们可称A 组件依赖于 B 组件java


2、什么是依赖注入。

在传统的程序设计过程当中,一般由调用者来建立被调用者的实例
spring

在依赖注入的模式下,建立被调用者的工做再也不由调用者来完成,所以称为控制反转;建立被调用者实例的工做一般由Spring 容器来完成,而后注入给调用者,所以也称为依赖注入app


3、依赖注入的好处。

依赖注入让 Spring 的 Bean 以被指文件组织在一块儿,而不是以硬编码的方式耦合在一块儿程序完成无须理会被调用者的实现,也不无须主动定位工厂,这是最好的解耦方式实例之间的依赖关系由 IoC 容器负责管理

ide

4、依赖注入的 Spring 实现

一、设值注入

设值注入是指 IoC 容器使用属性的 setting 方法来注入被依赖的实例。


先建立一个实体对象(Bean)
性能

[java] view plaincopy测试

  1. public class HelloWorld {    this

  2.     private String msg;    编码

  3.     

  4.     public String getMsg() {     spa

  5.         return msg;    .net

  6.     }    

  7.     public void setMsg(String msg) {    

  8.         this.msg = msg;    

  9.     }    

  10. }   


再配置文件applicationContext.xml,实例化bean 

[java] view plaincopy

  1. <bean id="helloBean" class="com.spring.demo.HelloWorld">    

  2.        <property name="msg" value="Hello World!"/>    

  3.  </bean>   

最后测试是否可以获得注入的bean,并打印出对象的属性。 

[java] view plaincopy

  1. public static void main(String[] args){    

  2.         //读取配置文件,得到BeanFactory    

  3.         ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");    

  4.         BeanFactory factory = context;    

  5.             

  6.         HelloWorld hello = (HelloWorld)factory.getBean("hello");    

  7.             

  8.         System.out.println(hello.getMsg());     

  9.  }   


二、构造注入

除了设值注入,还有另外一种注入方式,这种方式在构造实例时,已为其完成了依赖关系的初始化。这种利用构造器来设置依赖关系的方式,被称为构造注入。

先建立一个实体对象(Bean)

[java] view plaincopy

  1. public class HelloWorld {    

  2.     private String msg;    

  3.     

  4.     //须要一个默认无参构造器    

  5.     public HelloWorld(){}    

  6.         

  7.     public HelloWorld(String msg){    

  8.         this.msg = msg;    

  9.     }    

  10.         

  11.     public String getMsg() {    

  12.         return msg;    

  13.     }    

  14.     public void setMsg(String msg) {    

  15.         this.msg = msg;    

  16.     }    

  17. }   



再配置文件applicationContext.xml,实例化bean。

[java] view plaincopy

  1. <bean id="hello" class="com.spring.demo.HelloWorld">      

  2.      <constructor-arg index="0">     

  3.            <value>HelloWorld!</value>     

  4.        </constructor-arg>      

  5.  </bean>   



最后测试是否可以获得注入的bean,并打印出对象的属性。

[java] view plaincopy

  1. public static void main(String[] args){    

  2.         //读取配置文件,得到BeanFactory    

  3.         ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");    

  4.         BeanFactory factory = context;    

  5.             

  6.         HelloWorld hello = (HelloWorld)factory.getBean("hello");    

  7.             

  8.         System.out.println(hello.getMsg());     

  9.  }   


5、处理bean依赖关系的步骤

一、根据定义bean的配置建立并初始化BeanFactory实例 
二、每一个bean的依赖将以属性、构造器参数、或静态工厂方法参数的形式出现。当这些bean被实际建立时,这些依赖也将会提供给该bean。 
三、每一个属性或构造器参数既能够是一个实际的值,也能够是对该容器中另外一个bean的引用。 
四、每一个指定的属性或构造器参数值必须可以被转换成特定的格式或构造参数所需的类型。 

Spring 会在容器被建立时验证容器中每一个bean的配置,包括验证那些bean所引用的属性是否指向一个有效的bean。在bean被实际建立以前,bean的属 性并不会被设置。伴随着bean被实际建立,做为该bean的依赖bean以及依赖bean的依赖bean也将被建立和分配。



6、两种注入方式的对比

一、相比之下,设值注入具备以下的优势:

(1)、与传统的 JavaBean 的写法更类似,程序开发人员更容易理解、接受。经过 Setting 方法设定依赖关系显得更加直观、天然。
(2)、对于复杂的依赖关系,若是采用构造注入,会致使构造过于臃肿,难以阅读。Spring 在建立 Bean 实例时,须要同时实例化其依赖的所有实例,于是致使性能降低。而使用设值注入,则能避免这些问题。
(3)、尤为是在某些属性可选的状况下,多参数的构造器更加笨重。

二、构造注入也不是绝对不如设值注入,在某些特定的场景下,构造注入比设值注入更优秀。构造注入也有以下优点:

(1)、构造注入能够在构造器中决定依赖关系的注入顺序,有限依赖的优先注入。例如,组件中某些其余依赖关系的注入,尝尝须要依赖于 Datasource 的注入。采用构造注入,能够在代码中清晰地决定注入顺序。
(2)、对于依赖关系无须变化的 Bean ,构造注入更有用处。由于没有 setting 方法,全部的依赖关系所有在构造器内设定。所以,无须担忧后续代码对依赖关系产生的破坏。
(3)、依赖关系只能在构造器中设定,则只有组件的建立者才能改变组件的依赖关系。对组件的调用者而言,组件内部的依赖关系完成透明,更符合高内聚的原则。

两种方式总结:建议采用以设值注入为住,构造注入为辅的注入策略。对于依赖关系无须变换的注入,尽可能采用构造注入;而其余的依赖关系的注入,则考虑采用设值注入

相关文章
相关标签/搜索