天天看點

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.自動裝配不如顯示依賴注入精确。如果有可能盡量使用顯示依賴注入。