依賴注入深度剖析

1、循環依賴:

有兩個Bean——a和b,而這兩個Bean經過各自的構造函數互爲依賴項,那麼Spring容器就沒法實例化這兩個Bean:函數

public class A{this

private B b;spa

public A(B b){ci

    this.b=b;作用域

}io

}table

 

public class B{class

private A a;容器

public B(A a){配置

    this.a=a;

}

}

<bean id=」a」 class=」com.lizhen.A」>

    <constructor-arg ref=」b」 />

</bean>

 

<bean id=」b」 class=」com.lizhen.B」>

    <constructor-arg ref=」a」 />

</bean>

這是由於當第一個Bean被建立時,期待第二個Bean被注入到自身。然而,此時第二個Bean也處於建立階段,而且也期待第一個Bean做爲本身的依賴項。這樣就會在應用程序中致使BeanCurrentlyCreationException。但另外一方面,Setter注入可以處理此類循環。雖然Spring經過使用Setter注入容許循環依賴,但對於那些有循環依賴的Bean而言,Spring的不少其餘功能將沒法使用。所以,通常來講,不建議在配置中使用循環依賴。

2、依賴解析過程

Spring容器的啓動過程大體可分爲兩個主要階段:

①  容器處理配置元數據並創建元數據中存在的Bean定義,在該過程當中還會對這些Bean定義進行驗證。例如,檢查是否向<property>和<constructor—arg>元素提供正確的Bean引用,等等。然而,在該步驟中,Bean並無被建立,相關的屬性也沒有被注入。

②  首先完成Bean的建立,而後完成依賴注入。但實際上,並非全部的Bean都被建立;在容器啓動期間,僅建立了無狀態做用域的Bean。Bean的建立實際觸發了一連串其餘依賴Bean的建立,而這些依賴Bean又會觸發它們的依賴項的建立,以此類推。

一個Bean在被徹底建立且本身的依賴項被注入以前是不會做爲一個依賴項被注入到其餘Bean中去的。所以,必須確保被注入某一Bean中的Bean依賴項被徹底配置且能夠在目標Bean中引用。(惟一類外的是上面所說的循環依賴)

3、重寫Bean定義

重寫Spring容器中的Bean定義是可能的。每一個Bean都有身份(即id名),而Bean的名稱定義了本身的身份。若是建立了一個Bean定義,而該Bean的名稱已經賦予了其餘Bean定義,那麼第二個定義將重寫第一個定義。

4、depends-on特性

若是Bean  a直接或間接依賴Bean b,那麼能夠確定Spring容器將首先建立Bean b。然而,若是兩個Bean定義彼此之間沒有直接或間接依賴,那麼Bean建立的順訊就有Spring容器內部肯定。此時,沒法確保Bean b始終在Bean a以前被建立。有時,雖然Bean之間沒有彼此依賴,但他們卻須要彼此之間有一個特定的建立順序。例如,一個執行JVM級別初始化的Bean必須在其餘Bean以前被建立,由於這些Bean在被初始化以前必須先完成JVM級別的初始化。在此類狀況下,能夠在基於XML的配置中經過使用<bean>元素的depends-on特性來指定Bean  b 在Bean  a以前被建立。

<bean id=」a」 class=」com.lz.A」 depends-on=」b,c」 />

能夠在depends-on特性中列出多個Bean名稱。同時,在Bean析構階段和Bean初始化階段,depends-on特性也扮演了很是重要的角色。只有在無狀態Bean的狀況下,當該Bean使用了depends-on特性時,depends-on特性中所列舉的Bean才被銷燬。

做用:指定的Bean被建立以後纔會建立本類,不然就不會建立本類。

5、自動裝配

有時,並無必要顯示地在Bean定義中定義依賴項;可讓Spring容器自動地向Bean中注入依賴項。該過程成爲自動裝配。

自動裝配有三種模式:byType、byName和cinstructor

byType模式:

Spring首先經過Java反射查看Bean定義中的類,以便研究定義中的屬性,而後嘗試將容器中可用的Bean注入與器類型相匹配的屬性。該注入操做主要是經過調用這些屬性的Setter方法來完成的。例如:

 

<bean id=」a」 class=」com.lz.A」  autowire=」byType」 />

<bean id=」b」 class=」com.lz.B」  />

 

若是有多個Bean實例適合自動裝配到某一個特定的屬性,那麼依賴注入將會失敗。此時須要爲Spring容器提供幫助,以便肯定注入哪一個Bean實例。其中一種解決辦法是從自動裝配的候選Bean中進行過濾,並注入剩下的Bean。爲此,可使用<bean>元素的autowire-candidate特性:

 

<bean id=」a」 class=」com.lz.A」  autowire=」byType」 />

<bean id=」b」 class=」com.lz.B」  autowire-candidate=」false」 />

<bean id=」c」 class=」com.lz.C」  />

 

byName模式:

上邊狀況的另一種解決方法就是用byName自動裝配模式,這種狀況下,容器嘗試將屬性名與Bean名稱進行匹配,並注入匹配的Bean。

 

<bean id=」a」 class=」com.lz.A」  autowire=」byName」 />

<bean id=」b」 class=」com.lz.B」  />

在Spring容器中沒有候選Bean是將不會注入任何Bean,其默認屬性值保持不變。

 

constructor模式:

該模式相似於byType模式,但在使用constructor模式時,Spring容器嘗試找到那些類型與構造函數參數相匹配的Bean。一樣,若是針對某一參數有多個候選Bean,Spring沒法注入該參數。

相關文章
相關標籤/搜索