【轉】Spring學習筆記1—依賴注入(構造器注入、set注入和注解注入)


什么是依賴注入

在以前的java開發中,某個類中需要依賴其它類的方法時,通常是new一個依賴類再調用類實例的方法,這種方法耦合度太高並且不容易測試,spring提出了依賴注入的思想,即依賴類不由程序員實例化,而是通過spring容器幫我們new指定實例並且將實例注入到需要該對象的類中

 

依賴注入的方式

依賴注入有3種方式:構造器注入、set注入和注解注入。

1.構造器注入

構造器注入保證一些必要的屬性在Bean實例化時就得到設置,並且確保了Bean實例在實例化后就可以使用。

使用方式:

  1. 在類中,不用為屬性設置setter方法,但是需要生成該類帶參的構造方法。
  2. 在配置文件中配置該類的bean,並配置構造器,在配置構造器中用到了<constructor-arg>節點,該節點有四個屬性
    • index:指定注入屬性的順序索引,從0開始;
    • type:指該屬性所對應的類型;
    • ref:引用的依賴對象;
    • value:當注入的不是依賴對象,而是基本數據類型時,就用value;

例子1:

復制代碼
public class SpringAction {  
    //注入對象springDao  
    private SpringDao springDao;  
    private User user;  
      
    public SpringAction(SpringDao springDao,User user){  
        this.springDao = springDao;  
        this.user = user;  
        System.out.println("構造方法調用springDao和user");  
    }  
          
    public void save(){  
        user.setName("卡卡");  
        springDao.save(user);  
    }  
}  
復制代碼
復制代碼
    <bean name="springAction" class="com.bless.springdemo.action.SpringAction">  
        <!--(2)創建構造器注入,如果主類有帶參的構造方法則需添加此配置-->  
        <constructor-arg index="0" ref="springDao"></constructor-arg>  
        <constructor-arg index="1" ref="user"></constructor-arg>  
    </bean>  
    <bean name="springDao" class="com.bless.springdemo.dao.impl.SpringDaoImpl"></bean>  
    <bean name="user" class="com.bless.springdemo.vo.User"></bean>  
復制代碼

其中index屬性表示注入的bean在構造方法中的參數順序。

例子2:

有時需要聯合使用type和index才能確定匹配項和構造函數入參的對應關系,看下面的代碼。

復制代碼
public Car(String brand, String corp,double price){
    this.brand=brand;
    this.corp=corp;
    this.price=price;
}

public Car(String brand, String corp,int maxSpeed){
    this.brand=brand;
    this.corp=corp;
    this.maxSpeed=maxSpeed;
}
復制代碼

 這里,Car擁有兩個重載的構造函數,它們都有三個入參。針對這種情況,按照入參索引的配置方式又難以滿足要求了,這時需要聯合使用<constructor-arg>的type和index才能解決問題

復制代碼
<!-- 構造函數注入(通過入參類型和位置索引確定對應關系) -->
<!-- 對應public Car(String brand, String corp,int maxSpeed)構造函數 -->
<bean id="car3" class="com.spring.model.Car">  
    <constructor-arg index="0" type="java.lang.String" value="奔馳"></constructor-arg>
    <constructor-arg index="1" type="java.lang.String" value="中國一汽"></constructor-arg>
    <constructor-arg index="2" type="int" value="200"></constructor-arg>
</bean>
復制代碼

對於由於參數數目相同而類型不同所引起的潛在配置歧義問題,Spring容器可以正確啟動且不會給出報錯信息,它將隨機采用一個匹配的構造函數實例化Bean,而被選擇的構造函數可能並不是用戶所希望的。因此,必須特別謹慎,以避免潛在的錯誤。

 

2.set注入

set注入要求Bean提供一個默認的構造函數,並為需要注入的屬性提供對應的Setter方法。

Spring先調用Bean的默認構造函數實例化Bean對象,然后通過反射的方式調用Setter方法注入屬性值。

假設Bean顯示定義了一個帶參的構造函數,則需要同時提供一個默認無參的構造函數,否則使用屬性注入時將拋出異常。 

例子1:

復制代碼
package com.bless.springdemo.action;  
public class SpringAction {  
        //注入對象springDao  
    private SpringDao springDao;  
        //一定要寫被注入對象的set方法  
    public void setSpringDao(SpringDao springDao) {  
        this.springDao = springDao;  
    }  
  
    public void ok(){  
        springDao.ok();  
    }  
}  
復制代碼
<!--配置bean,配置后該類由spring管理-->  
    <bean name="springAction" class="com.bless.springdemo.action.SpringAction">  
        <!--(1)依賴注入,配置當前類中相應的屬性-->  
        <property name="springDao" ref="springDao"></property>  
    </bean>  
   <bean name="springDao" class="com.bless.springdemo.dao.impl.SpringDaoImpl"></bean>

這里不再使用“constructor-arg”而是使用“property”屬性。

 

3.注解注入

注解注入其實是使用注解的方式進行構造器注入或者set注入。

spring2.5開始提供了基於注解(Annotation-based)的配置,我們可以通過注解的方式來完成注入依賴。在Java代碼中可以使用 @Resource或者@Autowired注解方式來經行注入。

雖然@Resource和@Autowired都可以來完成注入依賴,但它們之間是有區別的:

  1. @Resource默認是按照名稱來裝配注入的,只有當找不到與名稱匹配的bean才會按照類型來裝配注入;
  2. @Autowired默認是按照類型裝配注入的,如果想按照名稱來轉配注入,則需要結合@Qualifier一起使用;
  3. @Resource注解是又J2EE提供,而@Autowired是由Spring提供;

例子:

復制代碼
package com.bless.springdemo.action;  
public class SpringAction {  
        //注入對象springDao 
    @Resource
    private SpringDao springDao;  
        //不需要要寫被注入對象的set方法,spring會幫你get/set 
       
    public void ok(){  
        springDao.ok();  
    }  
}  
復制代碼
<context:annotation-config/>

<bean name="springAction" class="com.bless.springdemo.action.SpringAction"> <!--不需要配置屬性,@Resource默認按照名稱裝配注入--> </bean> <bean name="springDao" class="com.bless.springdemo.dao.impl.SpringDaoImpl"></bean>

<context:annotation-config/>的作用是開啟注解。

@Autowired的同理,只不過默認是按照類型裝配注入。

 

補充:

@Autowired 可以對成員變量、方法以及構造函數進行注釋。那么對成員變量和構造函數進行注釋又有什么區別呢? 

先來看下面一段代碼:

復制代碼
@Autowired
private User user;
private String school;

public UserAccountServiceImpl(){
    this.school = user.getSchool();
}
復制代碼

這段代碼執行會報錯,因為Java類會先執行構造方法,然后再給注解了@Autowired 的user注入值,所以在執行構造方法的時候,就會報錯。

解決辦法是,使用構造器注入,如下:

復制代碼
private User user;
private String school;

@Autowired
public UserAccountServiceImpl(User user){
    this.user = user;
    this.school = user.getSchool();
}
復制代碼

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM