Spring的depends-on屬性Bean依賴

Spring內核研究-管理bean之間的關係一(depends-on)

depend-on用來表示一個Bean的實例化依靠另一個Bean先實例化。如果在一個bean A上定義了depend-on B那麼就表示:A 實例化前先實例化 B。
這種情況下,A可能根本不需要持有一個B對象。
比如說,你的DAO Bean實例化之前你必須要先實例化Database Bean,DAO Bean並不需要持有一個Database Bean的實例。因爲DAO的使用是依賴Database啓動的,如果Database Bean不啓動,那麼DAO即使實例化也是不可用的。這種情況DAO對Database的依賴是不直接的。
除了在DAO上使用構造函數注入Database Bean以外,Spring沒有任何依賴注入的關係能夠滿足上面的情況。但是DAO也許根本不需要Database的實例被注入,因爲DAO是通過JDBC訪問數據庫的,它不需要調用Database 上的任何方法和屬性。

在這種情況下你可以使用depends-on來定義在DAO被實例化之前先去實例化Database。你可這樣定義:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN" "http://www.springframework.org/dtd/spring-beans-2.0.dtd">
<beans>
 <bean name="dao" class="research.spring.beanfactory.ch3.Dao" depends-on="database" >
    </bean>

    <bean id="database" class="research.spring.beanfactory.ch3.Database">
    </bean>   

</beans>
通過定義depends-on=”database”可以控制Sping實例化dao的順序。在任何時候Spring總會保證實例化DAO之前先實例Database。
通常depends-on常常應用在上面的場景中。如果DAO depend-on Database的同時需要得到Database的實例,那麼使用構造函數注入是一個比較好的解決辦法。因爲構造函數注入的方式是要先實例化目標對象依賴的對象然後在實例化目標對象。
DAO depend-on Database時,也可以在DAO上定義setDatabase方法來接收一個Database的實例。這樣Sping會保證DAO創建前先創建Database實例,然後在把實例化DAO後調用DAO的setDatabase方法把剛纔創建的Database的實例注入給DAO。前提條件時Database必須定義成單例的。否則Spring在DAO depend-on Database時會創建一個Database的實例,在DAO.setDatabase時又會創建Database另外的一個實例。這種情況可能不是你想要的,而且很可能會造成比較隱蔽的錯誤。
使用set方法注入depend-on的對象:

<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> <bean name="dao" class="research.spring.beanfactory.ch3.Dao" depends-on="database "> <property name="database"> <ref bean="database"></ref> </property> </bean> <bean id="database" class="research.spring.beanfactory.ch3.Database"> </bean> </beans>


一般在depends-on一個對象並且又需要這個對象實例的情況下,我都建議你使用構造函數的注入方式替換depend-on。只有不能構造函數中添加依賴對象參數的情況下才使用上面例子裏的方式。
可以同時使用depends-on和構造函數注入,如A depends-on B 並且 new A(B b)。

<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> <bean name="dao" class="research.spring.beanfactory.ch3.Dao" depends-on="database"> <constructor-arg> <ref bean="database"></ref> </constructor-arg> </bean> <bean id="database" class="research.spring.beanfactory.ch3.Database"> </bean> </beans>


然而這種做法是不合適的,因爲在構在函數中注入依賴對象的方式可以包含depends-on的情況。也就時說new A(B b)包含了A depends-on B的所有情況。既然已經定義了new A(B b)就沒有必要在定義A depends-on B。所以,new A(B b)可以替代A depends-on B在A創建前必須創建B,而且A不需要使用B實例的情況下只能使用A depends-on B。

Spring允許Bean和Bean依賴的Bean(合作者)上同時定義depends-on。比如A depends-on B && B depends-on C && C depends-on D。下面這樣定義是合法的。Sping實例化他們的順序是D->C->B->A。

<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> <bean name="a" class="research.spring.beanfactory.ch3.A" depends-on="b" /> <bean name="b" class="research.spring.beanfactory.ch3.B" depends-on="c" /> <bean name="c" class="research.spring.beanfactory.ch3.C" depends-on="D" /> <bean name="d" class="research.spring.beanfactory.ch3.D" /> </beans>

但是Spring不允許A depends-on B && B depends-on A的情況。看下面的例子,由於D又依賴回A,這種在依賴關係中形成了一個閉環,Spring將無法處理這種依賴關係。所以下面的這種定義是不合法的。

<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> <bean name="a" class="research.spring.beanfactory.ch3.A" depends-on="b" /> <bean name="b" class="research.spring.beanfactory.ch3.B" depends-on="c" /> <bean name="c" class="research.spring.beanfactory.ch3.C" depends-on="D" /> <bean name="d" class="research.spring.beanfactory.ch3.D" depends-on="A" /> </beans>

一個Bean可以同時depends-on多個對象如,A depends-on D,C,B。可以使用“,”或“;”定義多個depends-on的對象。

<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> <bean name="a" class="research.spring.beanfactory.ch3.A" depends-on="d,c,b" /> <bean name="b" class="research.spring.beanfactory.ch3.B" /> <bean name="c" class="research.spring.beanfactory.ch3.C" /> <bean name="d" class="research.spring.beanfactory.ch3.D" /> </beans>


上面的例子中A的實例化需要先實例化D,C,B。Spring會按照depend-on中定義的順序來處理Bean。在這個例子裏Spring實例化對象 的順利是D->C->B->A。雖然實例化對象的順序和前面“A depends-on B && B depends-on C && C depends-on D”的情況一下,但是這裏的意義是完全不同的。不能用“A depends-on D,C,B”代替“A depends-on B && B depends-on C && C depends-on D”。

depends-on是一個非常又用的功能,藉助depends-on我們可以管理那些依賴關係不明顯或者沒有直接依賴關係的對象。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章