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>
<?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>
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>
<?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我們可以管理那些依賴關係不明顯或者沒有直接依賴關係的對象。