天天看点

Spring autowire 总结和例子

在应用中,我们常常使用<ref>标签为JavaBean注入它依赖的对象。但是对于一个大型的系统,这个操作将会耗费我们大量的资源,我们不得不花费大量的时间和精力用于创建和维护系统中的<ref>标签。实际上,这种方式也会在另一种形式上增加了应用程序的复杂性,那么如何解决这个问题呢?spring为我们提供了一个自动装配的机制,尽管这种机制不是很完善,但是在应用中结合<ref>标签还是可以大大的减少我们的劳动强度。前面提到过,在定义Bean时,<bean>标签有一个autowire属性,我们可以通过指定它来让容器为受管JavaBean自动注入依赖对象。

<bean>的autowire属性有如下六个取值,他们的说明如下: 

1、 No:即不启用自动装配。Autowire默认的值。这种情况下,用户必须自己去通过ref 指明被注入的bean ID

   如:<property name="myname" ref="studentName">

<property name="printer" ref="printer">

2、 byName:根据属性名自动装配。此选项将检查容器并根据名字查找与属性完全一致的bean(找该定bean的bean ID),并将其与属性自动装配。

 如: <bean id="userManagerTarget" autowire="byName">      

      <property name="baseDAO"/> </bean>    

这样对于bean userManagerTarget的属性baseDAO,spring就会自动去引用名为baseDAO的bean,也就是上面的声明和下面是等价的。

 <bean id="userManagerTarget" autowire="no">      

 <property name="baseDAO">   <ref local="baseDAO"/>      

  </property> 

</bean>

 这里,userManagerTarget类必须提供setter方法如下:

  void setBaseDAO(BaseDAO mydao){

   this.baseDAO=mydao;

}

3、 byType:通过属性的类型查找JavaBean依赖的对象并为其注入。比如类Computer有个属性printer,类型为Printer,那么,指定其autowire属性为byType后,Spring IoC容器会查找Class定义为Printer的bean,使用Seter方法为其注入。 

这里,Computer类必须提供setter方法如下:

  void setPrinter(Printer myprinter){

   this.printer=myprinter;

}

如果容器中存在一个与指定属性类型相同的bean,那么将与该属性自动装配;如果存在多个该类型bean,那么抛出异常,并指出不能使用byType方式进行自动装配;如果没有找到相匹配的bean,则什么事都不发生,也可以通过设置dependency-check="objects"让Spring抛出异常。

4、 constructor:通byType一样,也是通过类型查找依赖对象。与byType的区别在于它不是使用setter方法注入,而是使用构造器注入。 

constructor:与byType方式类似,不同之处在于它应用于构造器参数。如果容器中没有找到与构造器参数类型一致的bean, 那么抛出异常。 reference原文是: This is analogous to byType, but applies to constructor arguments. If there isn't exactly one bean of the constructor argument type in the bean factory, a fatal error is raised.

5、 autodetect:在byType和constructor之间自动的选择注入方式。 

6、 default:由上级标签<beans>的default-autowire属性确定。

byName示例:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd">
     <bean id="autowireTest1" class="com.test.spring.AutowireTest1" autowire="byName">
     </bean>
     <bean id="autowireTest2" class="com.test.spring.AutowireTest2">
     </bean>
</beans>      

Java 类:

package com.test.spring;

public class AutowireTest1 {
    
    private  AutowireTest2 autowireTest2;

    public AutowireTest2 getAutowireTest2() {
        return autowireTest2;
    }

    public void setAutowireTest2(AutowireTest2 autowireTest2) {
        this.autowireTest2 = autowireTest2;
    }
}
-------------------------------------------------------------------------------------------
package com.test.spring;

public class AutowireTest2 {

}      

测试:

package com.test.spring;

import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

public class T {
    ApplicationContext applicationcontext=null;
    @Before
    public void before() {
        System.out.println("》》》Spring ApplicationContext容器开始初始化了......");
        applicationcontext= new ClassPathXmlApplicationContext(new String[]{"test1-service.xml"});
        System.out.println("》》》Spring ApplicationContext容器初始化完毕了......");
    }
    @Test
    public void  test() {
        AutowireTest1 autowireTest1= applicationcontext.getBean(AutowireTest1.class);
        System.out.println(autowireTest1.getAutowireTest2());
    }
}      
Spring autowire 总结和例子

测试结果:

》》》Spring ApplicationContext容器开始初始化了......

2017-03-19 22:53:54  INFO:ClassPathXmlApplicationContext-Refreshing org[email protected]496419dc: startup date [Sun Mar 19 22:53:54 CST 2017]; root of context hierarchy

2017-03-19 22:53:54  INFO:XmlBeanDefinitionReader-Loading XML bean definitions from class path resource [test1-service.xml]

》》》Spring ApplicationContext容器初始化完毕了......

[email protected]

byType:

只需要将bean改为如下:

<bean id="autowireTest1" class="com.test.spring.AutowireTest1" autowire="byType">

测试结果:

》》》Spring ApplicationContext容器开始初始化了......
2017-03-19 22:53:54  
INFO:ClassPathXmlApplicationContext-Refreshing 
org[email protected]496419dc:
 startup date [Sun Mar 19 22:53:54 CST 2017]; root of context hierarchy
2017-03-19 22:53:54  INFO:XmlBeanDefinitionReader-Loading XML bean definitions from class path resource [test1-service.xml]
》》》Spring ApplicationContext容器初始化完毕了......
[email protected]

constructor:
   
只需要将bean改为如下:

<bean id="autowireTest1" class="com.test.spring.AutowireTest1" autowire="constructor">
对应AutowireTest1类改为:
      
package com.test.spring;

public class AutowireTest1 {
    
    private  AutowireTest2 autowireTest2;

    public AutowireTest1(AutowireTest2 autowireTest2) {
        this.autowireTest2 = autowireTest2;
    }
}      

测试结果输出:

》》》Spring ApplicationContext容器开始初始化了......

2017-03-20 09:13:48  INFO:ClassPathXmlApplicationContext-Refreshing org[email protected]4752dd7b: startup date [Mon Mar 20 09:13:48 CST 2017]; root of context hierarchy

2017-03-20 09:13:48  INFO:XmlBeanDefinitionReader-Loading XML bean definitions from class path resource [test1-service.xml]

》》》Spring ApplicationContext容器初始化完毕了......

[email protected]

总结:

  自动装配的好处:

     自动装配可以有效减少bean标签的<constructor-arg/>或<property/>元素的使用

 自动装配的局限性和不利条件:

    1.显示的依赖注入<constructor-arg/>或<property/>会重写自动装配。不能自动装配基本数据类型、字符串、数组等,这是自动装配设计的局限性。

    2.自动装配不如显示依赖注入精确。如果有可能尽量使用显示依赖注入。