在Spring中,對象無需自己負責查找或創建與其關聯的其他對象,相反,容器負責把需要相互協作的對象引用賦予各個對象。
創建應用對象之間協作關係的行爲即爲裝配。這也是依賴注入的本質。
1.創建Spring配置
Spring是一個基於容器的框架。如果沒有配置Spring,那麼它就是一個空容器。
Spring容器提供了兩種配置Bean的方式:傳統方法,配置XML配置文件;Spring3.0提供了基於Java註解的配置方式。
注入依賴的方式:
>.構造器注入:
eg.1默認構造器注入
<bean id="duke" class = "com.springaction.springidol.Juggler">
</bean>
eg.2有參構造函數注入
<bean id="duke" class = "com.springaction.springidol.Juggler">
<!--設置構造器參數爲15-->
<constructor-arg value="15">
</constructor-arg>
</bean>
對應的構造函數爲
public void Juggler(int bags)
{
this.bags = bags;
}
eg.3構造函數參數有對象
<bean id="duke" class = "com.springaction.springidol.Juggler">
<!--構造器一個參數爲15-->
<constructor-arg value="15">
</constructor-arg>
<!--構造器另一個參數通過ref將屬性爲sonnet29的Bean引用傳遞給構造器-->
<constructor-arg ref="sonnet29">
</constructor-arg>
</bean>
<bean id="sonnet29" class="com.springaction.springidol.Sonnet29">
</bean>
當Spring加載到sonnet29和duke的<bean>聲明時,它所執行的邏輯本質上是如下的Java代碼:
Poem sonnet29 = new Sonnet29();
Performer duke = new PoeticJuggler(15, sonnet29);
>.通過工廠方法創建Bean
如果要聲明的Bean沒有公有構造函數,則可以通過靜態工廠方法實例化對象
<!--通過getInstance方法創建Stage單例對象-->
<bean id="stage" class="com.springactin.springidol.Stage"
factory-method="getInstance">
</bean>
2.Bean作用域
所有的Spring Bean默認都是單例的。
如果要Spring在每次請求時都生成一個新的Bean實例,可以給Bean配作用域: scope="prototype"
Spring提供瞭如下作用域選項:
注:Spring的單例Bean只能保證在每個應用上下文中只有一個Bean實例。
3.Bean的初始化和銷燬
當實例化一個Bean時,可能需要執行一些初始化操作來確保Bean處於可用狀態。同樣,當不再需要Bean,將其從容器中移除時,可能還需要按順序執行一些清除工作。爲了滿足初始化和銷燬Bean的需求,Bean提供了Bean生命週期的鉤子方法。
爲了定義Bean的初始化和銷燬操作,只需要使用init-method和detroy-method參數來配置</bean>元素。
eg.
<bean id="test_Bean" class="test.domain.TestClass"
init-method="start"
destroy-method="stop">
</bean>
當test_Bean Bean實例化後悔立即調用start()方法做初始化操作。當該Bean從容器中移除和銷燬前,會調用stop()方法完成一些清理工作。
4.注入Bean的屬性
Spring可藉助屬性的set方法來配置屬性的值,以實現setter方法的注入。前提是JavaBean的屬性擁有一組存取器方法,以setXXX()和getXXX()形式存在。
>.注入簡單的值
<bean id="test_Bean" class="spirng.domain.test.TestClass">
<property name="age" value="25" />
<property name="sex" value="male" />
</bean>
Spring將根據Bean屬性的類型自動判斷value值的正確類型。
>.引用其他Bean:依賴注入的真正價值在於把相互協作的對象裝配在一起,而不需要這些對象自己負責裝配。
eg.
<bean id="kenny" class="spring.domain.Instrumentalist">
<property name="song" value="Jingle Bells" />
<property name="instrument" ref="piano" />
</bean>
<bean id="piano" class="spring.domain.Piano" />
這樣,kenny就可以演奏鋼琴了,這是面向接口編程的好處。Instrumentalist這個類只是通過Instrument接口來了解它的instrument屬性。所以Instrumentalist不需要任何改變就可以支持一個Instrument接口的新實現。
>.內部bean
上面的piano Bean可以被任何其他Bean所共享。
<bean id="kenny" class="spring.domain.Instrumentalist">
<property name="song" value="Jingle Bells" />
<property name="instrument" >
<bean class="spring.domain.Piano" >
</bean>
</bean>
上面這個內部Bean就爲kenney所獨自擁有了,其他Bean無法獲得。
內部Bean並不僅限於setter注入,還可以把內部Bean裝配到構造方法的入參中。
>.使用Spring命名空間p裝配屬性。
>.裝配集合:配置集合類型的Bean屬性時,Spring提供了4種類型的集合配置元素。
eg1.裝配List、Set和Array
public class OneManBand implements Performer
{
private Collection<Instrument> instruments;
public OneManBand()
{
}
public void perform()
throw PerformanceException
{
for(Instrument instrument: instruments)
{
instrument.play();
}
}
public void setInstruments(Collection<Instrument> instruments)
{
this.instruments = instruments;
}
}
對於上面的JavaBean,Spring提供樂器集合方法如下:
(1).List
<bean id="hank" class="spring.domain.test.OneManBand">
<property name="instruments">
<list>
<ref bean="guitar"/>
<ref bean="cymbal"/>
<ref bean="harmonica" />
</list>
</property>
</bean>
(2).Set:將上面的 <list> 換成 <set> 即可。
無論<list>還是<set>都可用來裝配類型爲Collection的任意實現或者數組的屬性。
eg2.裝配Map集合
public class OneManBand implements Performer
{
private Collection<String, Instrument> instruments;
public OneManBand()
{
}
public void perform()
throw PerformanceException
{
for(String key: instruments.keySet())
{
Instrument instrument = instruments.get(key);
instrument.play();
}
}
public void setInstruments(Map<String, Instrument> instruments)
{
//以Map類型注入instruments
this.instruments = instruments;
}
}
<bean id="hank" class="spring.domain.test.OneManBand">
<property name="instruments">
<map>
<entry key="GUITAR" bean="guitar"/>
<entry key="CYMBAL" bean="cymbal"/>
<entry key="HARMONICA" bean="harmonica" />
</map>
</property>
</bean>
>.使用SpEL表達式裝配:可以爲屬性裝配只有在運行期才知道的值。