單例注入多例


      Spring bean容器中的bean有單例bean,也有多例bean。當我們需要給一個單例beanA注入一個單例beanB,或者給一個多例beanA注入一個多例或單例beanB時,都可以通過配置讓Spring的bean容器幫我們完成。但如果我們需要給一個單例beanA注入一個多例beanB時,僅僅通過配置Spring是無法幫我們的單例beanA注入一個多例beanB的,即無法讓我們每次使用beanB時都使用的是一個全新的beanB。因為beanA只初始化一次,相對應的Spring只會給beanA注入一個beanB。解決辦法是給beanA注入一個ApplicationContext,這樣我們就可以在每次需要使用beanB時都從ApplicationContext中獲取一個新的beanB。
      注入ApplicationContext有兩種方式,實現ApplicationContextAware接口和通過@Autowired或@Resource注解標注讓Spring進行自動注入。
     

實現ApplicationContextAware接口
       ApplicationContextAware接口中定義一個setApplicationContext()方法,對於實現了該接口的bean,Spring將通過調度對應的setApplicationContext()方法將當前ApplicationContext傳遞過去。

public class Hello implements ApplicationContextAware {
    
    private ApplicationContext applicationContext;

    /**
     * Spring將通過該方法給我們的bean注入當前的ApplicationContext
     */
    public void setApplicationContext(ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }
    
}

通過注解標注
  在使用注解進行配置時,我們也可以通過注解來告訴Spring要為當前的bean注入哪些內容。對於ApplicationContext也是一樣的,可以通過對應的注解來告訴Spring將為我們注入對應的ApplicationContext。自動注入的注解可以是@Resource,也可以是@Autowired。

public class Hello {
    
    private ApplicationContext applicationContext;

    @Resource
    public void setApplicationContext(ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }
    
}

Spring有一種機制,可以動態的實現或重寫bean容器中指定bean的指定方法,然后將返回值指定為bean容器中的另一個bean

1、在beanA對應的類中定義一個方法用來獲取BeanB,有這么一個方法就行,可以是空實現,到時候將由Spring來為我們重寫或實現,然后返回一個BeanB類型的bean。為此,可以將我們的BeanA如下定義:

public class BeanA {

    /**
     * 需要使用到BeanB的方法
     */
    public void doSomething() {
        BeanB beanB = this.getBeanB();
        System.out.println(beanB);
        //...
    }
    
    /**
     * 定義一個返回值為BeanB的方法,用來獲取BeanB類型的bean,該方法將由Spring來重寫。
     * @return
     */
    public BeanB getBeanB() {
        return null;
    }
    
}

2、在ApplicationContext中定義一個單例beanA和一個多例beanB,同時通過lookup-method元素指定beanAgetBeanB方法將會被Spring重寫並返回bean容器中的beanB

    <bean id="beanB" class="com.app.BeanB" scope="prototype"/>
    <bean id="beanA" class="com.app.BeanA">
        <!-- 表示將由Spring重寫getBeanB()方法,並返回名為beanB的bean -->
        <lookup-method name="getBeanB" bean="beanB"/>
    </bean>

  經過以上兩步以后每次在調度beanA的getBeanB()方法時,Spring都重新從bean容器中獲取一個beanB,因為beanB定義為多例形式,所以每次都會獲取一個全新的BeanB對象。

  在給一個bean指定了lookup-method后,Spring將通過CGLIB動態的生成一個該bean對應類型的子類,然后在該子類中實現或重寫lookup-method元素指定的方法,並從bean容器中獲取lookup-method元素指定的bean作為返回值進行返回。

      當bean指定的類型是一個抽象類且lookup-method指定的方法是一個抽象方法時,Spring就將實現該抽象方法,否則就是重寫。定義lookup-method的bean真正的類型是Spring動態生成類的類型,但是它可以被當做bean本身指定的類型使用,因為動態生成的類就是繼承自bean本身指定的類型的。

  由於Spring是需要動態生成類來重寫或實現指定的方法的,所以我們必須確保由lookup-method指定的方法是可以被重寫的,這就要求該方法對子類是可訪問的,而且不能是final型的。具體來講lookup-method元素指定的方法需要具有如下形式:

<public|protected> [abstract] <return-type> methodName(no-arguments)

      如你所見,lookup-method指定的方法還不能有參數。

參考:

     https://blog.csdn.net/elim168/article/details/74915352 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM