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
元素指定beanA
的getBeanB
方法將會被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