1. 程式人生 > >Bean的兩種依賴注入方式

Bean的兩種依賴注入方式

依賴是指物件之間的關係,依賴注入的兩種主要方式:

基於構造器注入Constructor-based

基於setter方法注入Setter-based

經常會有同學把依賴注入和bean例項化搞混。例項化是建立物件,相當於new這個操作符;而依賴注入是注入物件方法的引數或物件的屬性(可以理解成給它們賦值)。

其實我們在介紹例項化bean (http://blog.csdn.net/shymi1991/article/details/48153293)   的時候,除了空構造器的例子,其他例子已經涉及到了依賴注入,只是這裡注入的是java基本型別,用的是基於構造器的注入方法

下面詳細介紹兩種注入方法

一、構造器注入:

呼叫帶參構造器來實現(靜態工場方法的引數也可以看做是這一型別),這種方法bean的例項化和依賴注入是同時進行的。

可以根據構造器引數的 索引、型別和名稱來注入。

package examples;

public class ExampleBean {

    // No. of years to the calculate the Ultimate Answer
    private int years;

    // The Answer to Life, the Universe, and Everything
    private String ultimateAnswer;

    public ExampleBean(int years, String ultimateAnswer) {
        this.years = years;
        this.ultimateAnswer = ultimateAnswer;
    }
}
根據索引 index
<bean id="exampleBean" class="examples.ExampleBean">
  <constructor-arg index="0" value="7500000"/>
  <constructor-arg index="1" value="42"/>
</bean>

根據型別 type
<bean id="exampleBean" class="examples.ExampleBean">
  <constructor-arg type="int" value="7500000"/>
  <constructor-arg type="java.lang.String" value="42"/>
</bean>
根據名稱name
<bean id="exampleBean" class="examples.ExampleBean">
  <constructor-arg name="years" value="7500000"/>
  <constructor-arg name="ultimateAnswer" value="42"/>
</bean>

上例注入的是常量,注入的引數也可以是其他型別,如 引用(其他的bean)。

例子:

package x.y;

public class Foo {
    public Foo(Bar bar, Baz baz) {
        // ...
    }
}
   
	 <bean id="barBean" class="x.y.Bar"></bean>
	 <bean id="bazBean" class="x.y.Baz"></bean>
	 <bean name="foo" class="x.y.Foo">
	     <constructor-arg ref="barBean"/>
	     <constructor-arg ref="bazBean"/>
	 </bean>
 


二、setter注入:

通過  setter方法的引數實現,其實配置跟基於構造器的差不多,屬性是property。

public class ExampleBean {

    private AnotherBean beanOne;
    private YetAnotherBean beanTwo;
    private int i;

    public void setBeanOne(AnotherBean beanOne) {
        this.beanOne = beanOne;
    }

    public void setBeanTwo(YetAnotherBean beanTwo) {
        this.beanTwo = beanTwo;
    }

    public void setIntegerProperty(int i) {
        this.i = i;
    }    
}
<bean id="anotherExampleBean" class="examples.AnotherBean"/>
<bean id="yetAnotherBean" class="examples.YetAnotherBean"/>      
<bean id="exampleBean" class="examples.ExampleBean">

  <!-- 使用內嵌的 <ref/> 元素 -->
  <property name="beanOne">
  	<ref bean="anotherExampleBean"/>
  </property>

  <!-- 使用ref屬性 -->
  <property name="beanTwo" ref="yetAnotherBean"/>
  <property name="integerProperty" value="1"/>
</bean>
其實基於constructor和基於setter的引數注入 最終效果是一樣的,那麼在實際運用中選擇哪種方式呢?Spring小組建議用setter,因為過多的引數會顯得constructor很笨重;而且基於setter的引數配置利於後續修改。但有的Purists更傾向於用基於constructor,因為它在初始化的過程中就一併注入引數。 注:<property />和<constructor-arg  />的很多屬性都有其對應的內嵌元素,兩種格式的效果是一樣的,可看做是全寫和簡寫。下面是不同引數型別的注入全寫和簡寫:

1)常量值(基礎型別、String)

寫:<property name="message" value="常量"/>

全寫:<property name="message"><value>常量</value></property>

2)引用

寫:<property name="message" ref="引用"/>

全寫:<property name="message"><ref bean="引用"/></property>

3)陣列:<array>沒有簡寫形式

4)列表:<list>沒有簡寫形式

5)集合:<set>沒有簡寫形式

6)字典

簡寫:<map>

<entry key="鍵常量" value="值常量"/>

<entry key-ref="鍵引用"value-ref="值引用"/>

</map>

全寫:<map>

<entry><key><value>鍵常量</value></key><value>值常量</value></entry>

<entry><key><refbean="鍵引用"/></key><ref bean="值引用"/></entry>

</map>