Spring Bean屬性註入的兩種方式詳解

屬性註入概念

Spring 屬性註入(DI依賴註入)有兩種方式:setter註入構造器註入

這個註入的屬性可以是普通屬性(基本數據類型與String等),也可以是一個引用數據類型(主要是對象),或者是一個集合(list、map、set等)

下表是屬性註入bean標簽中常用的元素

元素名稱 描述
constructor-arg 構造器註入。該元素的 index 屬性指定構造參數的索引(從 0 開始),type 屬性指定構造參數的類型(type也可以不寫,spring會自動識別參數的類型)
property setter註入。該元素的 name 屬性用於指定 Bean 類中相應的屬性名(成員變量名) 。
ref <property> 和 <constructor-arg> 的子元索,用於引用指定bean實例,即 <bean> 元素中的 id 或 name 屬性。
value <property> 和 <constractor-arg> 的子元素,用於直接指定常量值。

一、構造器註入

先來介紹下構造器註入:Spring通過調用構造方法為成員變量賦值

  • 使用構造函數實現屬性註入大致步驟如下:
  • 在類中添加一個有參構造方法,構造方法內的每一個參數代表一個需要註入的屬性;
  • 在 Spring 的配置文件中定義Bean;
  • 在 <bean> 元素內使用 <constructor-arg> 元素,對構造函數內的屬性進行賦值,Bean 的構造方法內有多少參數,就需要使用多少個 <constructor-arg> 元素。

下面通過示例介紹如何使用構造器註入

示例1

1.創建員工類Employee和部門類Dept,並添加有參構造方法(關鍵!)

/*員工類Employee*/
public class Employee {
    //員工編號
    private String empNo;
    //員工姓名
    private String empName;
    //部門信息
    private Dept dept;
    //有參構造方法
    public Employee(String empNo, String empName, Dept dept) {
        this.empNo = empNo;
        this.empName = empName;
        this.dept = dept;
    }
    ----省略toString方法------  
}

/*部門類Dept*/
public class Dept {
    //部門編號
    private String deptNo;
    //部門名稱
    private String deptName;
    //有參構造方法
    public Dept(String deptNo, String deptName) {
        this.deptNo = deptNo;
        this.deptName = deptName;
    }
    ----省略toString方法------
}

2.編寫spring配置文件

<!--部門類屬性註入-->
<bean id="dept" class="com.bighorn.pojo.Dept">
    <constructor-arg index="0" value="1"/>
    <constructor-arg index="1" value="後端組"/>
</bean>
<!--員工類屬性註入-->
<bean id="employee" class="com.bighorn.pojo.Employee">
    <constructor-arg index="0" value="1"/>
    <constructor-arg index="1" value="bighorn"/>
    <constructor-arg index="2" ref="dept"/>
</bean>

3.編寫運行程序

public static void main(String[] args) {
    //獲取IoC容器
    ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
    //從容器中獲取對象
    Employee employee = context.getBean("employee", Employee.class);
    System.out.println(employee);
}

結果如下圖

註意點

spring識別有參構造方法的參數的三種形式:

1.以index識別,案例一就是如此

<bean id="dept" class="com.bighorn.pojo.Dept">
    <constructor-arg index="0" value="1"/>
    <constructor-arg index="1" value="後端組"/>
</bean>

2.以name識別,如下

<bean id="dept" class="com.bighorn.pojo.Dept">
    <constructor-arg name="deptNo" value="1"/>
    <constructor-arg name="deptName" value="後端組"/>
</bean>

3.以type識別,如下

<bean id="dept" class="com.bighorn.pojo.Dept">
    <constructor-arg type="int" value="1"/>
    <constructor-arg type="java.lang.String" value="後端組"/>
</bean>

三種形式各有各的好處和壞處。
以type識別不適合有多個參數類型相同的情況;以index形式識別,如果參數順序變瞭又要重改;以name形式識別,如果參數名變瞭也要重改。總之,都不太利於解耦

二、setter註入

下面來介紹下setter註入:Spring通過調用setter方法為成員變量賦值。

在【Spring學習筆記(二)】提到過,在 Spring 實例化 Bean 時,IoC 容器會先調用默認構造方法實例化 Bean,然後通過反射機制調用這個 Bean 的 setXxx() 方法,將屬性值註入到 Bean 中。

使用setter註入實現屬性註入大致步驟如下:

  • 在 類中提供一個默認的無參構造方法(在沒有帶參構造方法的情況下,可省略),並為所有需要註入的屬性提供一個 setter 方法
  • 在 Spring 的 XML 配置文件中定義Bean
  • 使用 <property> 元素對各個屬性進行賦值。

下面通過示例介紹如何使用setter註入方法

示例2

1.創建員工類Employee和部門類Dept,與示例一不同的是,需要添加各個成員變量的setter方法,也需要提供一個無參構造方法

/*員工類Employee*/
public class Employee {
    //員工編號
    private String empNo;
    //員工姓名
    private String empName;
    //部門信息
    private Dept dept;
    //無參構造方法,在沒有其他帶參構造方法的情況下,可以省略
    public Employee() {
    }   
    //各個屬性的setter方法
    public void setEmpNo(int empNo) {
        this.empNo = empNo;
    }
    public void setEmpName(String empName) {
        this.empName = empName;
    }
    public void setDept(Dept dept) {
        this.dept = dept;
    }
    ----省略toString方法------  
}

/*部門類Dept*/
public class Dept {
    //部門編號
    private String deptNo;
    //部門名稱
    private String deptName;
    //無參構造方法,在沒有其他帶參構造方法的情況下,可以省略
    public Dept() {
    }
    //各個屬性的setter方法
    public void setDeptNo(int deptNo) {
        this.deptNo = deptNo;
    }
    public void setDeptName(String deptName) {
        this.deptName = deptName;
    }
    ----省略toString方法------
}

2.編寫spring配置文件

<!--使用 property 元素完成屬性註入
        name: pojo類中的屬性名稱
        value: 向屬性註入的值 
     -->
<!--部門類屬性註入-->
<bean id="dept" class="com.bighorn.pojo.Dept">
    <property name="deptNo" value="2"/>
    <property name="deptName" value="前端組"/>
</bean>
<!--員工類屬性註入-->
<bean id="employee" class="com.bighorn.pojo.Employee">
    <property name="empNo" value="114514"/>
    <property name="empName" value="lzh"/>
    <property name="dept" ref="dept"/>
</bean>

3.編寫運行程序

public static void main(String[] args) {
    //獲取IoC容器
    ApplicationContext context = new ClassPathXmlApplicationContext("applicationContext.xml");
    //從容器中獲取對象
    Employee employee = context.getBean("employee", Employee.class);
    System.out.println(employee);
}

結果如下圖

三、如何選擇註入方式

如果對象在創建的過程中必須要註入指定的參數,則可以使用構造器註入行,因為使用setter註入有概率不進行註入導致null對象出現

如果對象在創建過程中註入的參數可有可無 ,則可以使用setter註入

常用的是setter註入方式,有必要時可以兩者結合使用

到此這篇關於Spring Bean屬性註入的兩種方式詳解的文章就介紹到這瞭,更多相關Spring Bean屬性註入內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: