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

什麼是依賴注入

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

 

依賴注入的方式

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

1.構造器注入

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

使用方式:less

  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:this

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

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才能解決問題.net

<!-- 構造函數注入(經過入參類型和位置索引肯定對應關係) -->
<!-- 對應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,而被選擇的構造函數可能並非用戶所但願的。所以,必須特別謹慎,以免潛在的錯誤。code

 

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();
}

 

 

參考:

@Autowired和構造方法執行的順序解析

相關文章
相關標籤/搜索