單例Bean注入多例Bean屬性失效問(wèn)題的四種解決方案
問(wèn)題描述
在實(shí)際的開(kāi)發(fā)過(guò)程中,我們有可能會(huì)遇到這樣一個(gè)場(chǎng)景:多例對(duì)象 A 需要作為屬性注入給單例對(duì)象 B,但是我們每次獲取 B 的時(shí)候,發(fā)現(xiàn)注入的 A 每次都是同一個(gè),并不是多例的。也就是下面這個(gè)代碼:
@Component @Scope("prototype") public class A { } @Component public class B { @Autowired private A a; @Override public String toString() { return "B{" + "a=" + a + '}'; } }
@Test public void test1() { B b1 = context.getBean("b", B.class); B b2 = context.getBean("b", B.class); System.out.println(b1); System.out.println(b2); }
輸入內(nèi)容如下:
從結(jié)果可以看出,B 注入的 A 是同一個(gè)對(duì)象,而不是期望的多例對(duì)象。
問(wèn)題原因
基于前文的內(nèi)容:《Bean的創(chuàng)建過(guò)程超詳細(xì)解析》,Spring 在第一次創(chuàng)建單例對(duì)象 B 的時(shí)候,會(huì)進(jìn)行屬性的填充,此時(shí)會(huì)調(diào)用工廠獲取 A 的多例對(duì)象。創(chuàng)建好 B 之后就將 B 緩存起來(lái),下次獲取直接從緩存中獲取 B,拿到后直接返回,不會(huì)再次去工廠中獲取 A 對(duì)象了,所以這就是作用域失效的根本原因。
問(wèn)題解決
要想解決此問(wèn)題,我們需要延遲獲取多例對(duì)象。這里提供四種方案可供參考:
方案一:作用域指定代理
@Component @Scope(value = "prototype" , proxyMode = ScopedProxyMode.TARGET_CLASS) public class A { } @Component public class B { @Autowired private A a; @Override public String toString() { return "B{" + "a=" + a + '}'; } }
這樣表示每次獲取 A 都是獲取的代理的對(duì)象,只要在代理上調(diào)用方法,每次獲取都會(huì)根據(jù)作用域重新獲取。
方案二:指定懶加載
@Component @Scope("prototype") public class A { } @Component public class B { @Lazy @Autowired private A a; @Override public String toString() { return "B{" + "a=" + a + '}'; } }
使用懶加載一樣會(huì)創(chuàng)建代理的對(duì)象,只要在代理上調(diào)用方法,每次獲取都會(huì)根據(jù)作用域重新獲取。
方案三:使用對(duì)象工廠 ObjectFactory
@Component @Scope("prototype") public class A { } @Component public class B { @Autowired private ObjectFactory<A> a; @Override public String toString() { return "B{" + "a=" + a.getObject() + '}'; } }
方案四:從容器獲取
@Component @Scope("prototype") public class A { } @Component public class B { @Autowired private ApplicationContext context; @Override public String toString() { return "B{" + "a=" + context.getBean("a") + '}'; } }
@Component @Scope("prototype") public class A { } @Component public class B implements BeanFactoryAware { private BeanFactory beanFactory; @Override public String toString() { return "B{" + "a=" + beanFactory.getBean("a") + '}'; } @Override public void setBeanFactory(BeanFactory beanFactory) throws BeansException { this.beanFactory = beanFactory; } }
以上就是單例Bean注入多例Bean屬性失效問(wèn)題的四種解決方案的詳細(xì)內(nèi)容,更多關(guān)于單例Bean注入多例失效的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
學(xué)生視角手把手帶你寫(xiě)Java?線程池改良版
作者是一個(gè)來(lái)自河源的大三在校生,以下筆記都是作者自學(xué)之路的一些淺薄經(jīng)驗(yàn),如有錯(cuò)誤請(qǐng)指正,將來(lái)會(huì)不斷的完善筆記,幫助更多的Java愛(ài)好者入門(mén)2022-03-03SpringBoot通過(guò)tractId操作日志鏈路跟蹤
這篇文章給大家介紹SpringBoot通過(guò)tractId操作日志鏈路跟蹤,通過(guò)tractId,即可完成對(duì)從一個(gè)請(qǐng)求進(jìn)入系統(tǒng)到請(qǐng)求結(jié)束的日志追蹤,本文給大家介紹的非常詳細(xì),需要的朋友參考下吧2023-10-10使用IDEA向Gitee提交SpringBoot項(xiàng)目進(jìn)行遠(yuǎn)程管理
本文主要介紹了使用IDEA向Gitee提交SpringBoot項(xiàng)目進(jìn)行遠(yuǎn)程管理,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-01-01使用java文件過(guò)濾器輸出制定格式文件路徑的實(shí)例代碼
這篇文章主要介紹了使用java文件過(guò)濾器輸出制定格式文件路徑的方法,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2019-11-11動(dòng)態(tài)修改spring?aop?切面信息提升自動(dòng)日志輸出框架效率
這篇文章主要為大家介紹了動(dòng)態(tài)修改spring?aop切面信息提升自動(dòng)日志輸出框架效率,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-07-07Spring Boot數(shù)據(jù)庫(kù)鏈接池配置方法
這篇文章主要介紹了Spring Boot數(shù)據(jù)庫(kù)鏈接池配置方法,需要的朋友可以參考下2017-04-04