7.9.3:協調範圍不同步的Bean

來源:互聯網
上載者:User

當兩個singleton範圍Bean存在依賴關係時,或prototype範圍Bean依賴singleton範圍Bean時,不會有任何問題。

但當singleton範圍Bean依賴prototype範圍Bean時,singleton範圍Bean只有一次初始化的機會,它的依賴關係也只在初始化階段被設定,它所依賴的prototype範圍Bean則需要每次都得到一個全新的Bean執行個體,這將會導致singleton範圍的Bean的依賴得不到即時更新。

singleton Bean依賴於prototype Bean時,當Spring容器初始化時,它會初始化容器中所有singleton Bean,此時prototype Bean被建立出來,並注入到singleton Bean中------當singleton Bean建立完成後,它就持有了一個prototype Bean,容器再不會為singleton Bean執行注入了。

由於singleton Bean具有單例行為,當用戶端多次請求singleton Bean時,Spring返回給用戶端的將是同一個singleton Bean執行個體,這不存在任何問題。問題是:如果用戶端多次請求singleton Bean、並調用singleton Bean去調用prototype Bean的方法時,始終都是調用同一個prototype Bean執行個體,這就違背了設定prototype Bean的初衷:本來希望它具有prototype行為,但實際上它卻表現出singleton行為。

這就是問題的所在:當singleton範圍的Bean依賴於prototype範圍的Bean時,會產生不同步的現象。

解決該問題有如下兩種思路:

① 部分放棄依賴注入:singleton範圍Bean每次需要prototype範圍Bean時,主動向容器請求新的Bean執行個體,即可保證每次注入的prototype Bean執行個體都是最新的執行個體。

② 利用方法注入。

第一種方式顯然不是一個好的做法,代碼主動請求新的Bean執行個體,必然導致代碼與Spring API耦合,造成代碼嚴重汙染。

通常情況下,我們採用第二種做法,使用方法注入。

方法注入通常使用lookup方法注入,利用lookup方法注入可以讓Spring容器重寫容器中Bean的抽象或具體方法,返回尋找容器中其他Bean的結果,被尋找的Bean通常是一個non-singleton Bean。Spring通過使用CGLIB庫修改用戶端的二進位碼,從而實現上述的要求。

Axe.java :

public interface Axe {public String chop();}

SteelAxe.java :

public class SteelAxe implements Axe {@Overridepublic String chop() {return "鋼斧砍柴真快";}public SteelAxe() {System.out.println("Spring執行個體化依賴Bean:SteelAxe執行個體...");}}

Person.java :

public interface Person {public void useAxe();}

Chinese.java :

public abstract class Chinese implements Person{public Chinese() {System.out.println("Spring執行個體化主調Bean:Chinese執行個體...");}//singleton Bean裡增加一個抽象方法//方法的傳回值類型是被依賴的Beanpublic abstract Axe getAxe();@Overridepublic void useAxe() {System.out.println("正在使用"+getAxe()+"砍柴!");System.out.println(getAxe().chop());}}

bean.xml核心配置:

 <bean id="chinese" class="com.bean.Chinese">    <lookup-method name="getAxe" bean="steelAxe"/> </bean>   <bean id="steelAxe" class="com.bean.SteelAxe" scope="prototype"/>

Test.java :

public class Test {public static void main(String[] args) {ApplicationContext ctx=new ClassPathXmlApplicationContext("bean.xml");Person p=(Person) ctx.getBean("chinese");p.useAxe();p.useAxe();}}

運行Test.java,控制台輸出:

SteelAxe被部署成prototype範圍Bean,並被一個singleton範圍Bean所依賴。如果讓Spring容器直接將prototype範圍的Bean注入singleton範圍Bean,就會出現不同步的問題。為瞭解決這個問題,我們在singleton Bean裡新增一個抽象方法,該方法的傳回值類型是被依賴的Bean,該方法是一個抽象方法,其實現由Spring完成。問題是:Spring怎麼知道如何?該方法呢?為了讓Spring知道如何?該方法,我們需要在設定檔中使用<lookup-method.../>元素來配置這個方法。

使用<lookup-method.../>元素需要指定如下兩個屬性:

① name:指定需要讓Spring實現的方法。

② bean:指定Spring實現該方法後的傳回值。

程式的執行結果表明:使用lookup方法注入後,系統每次調用getAxe( )方法都將產生一個新的SteelAxe執行個體,這就可以保證當singleton範圍的Bean需要全新的Bean執行個體時,直接調用getAxe( )方法即可,從而可以避免一直使用最早注入的Bean執行個體。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.