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
根據名稱name<bean id="exampleBean" class="examples.ExampleBean"> <constructor-arg type="int" value="7500000"/> <constructor-arg type="java.lang.String" value="42"/> </bean>
<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>