單例Bean注入多例Bean屬性失效問題的四種解決方案
問題描述
在實(shí)際的開發(fā)過程中,我們有可能會遇到這樣一個場景:多例對象 A 需要作為屬性注入給單例對象 B,但是我們每次獲取 B 的時候,發(fā)現(xiàn)注入的 A 每次都是同一個,并不是多例的。也就是下面這個代碼:
@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 是同一個對象,而不是期望的多例對象。
問題原因
基于前文的內(nèi)容:《Bean的創(chuàng)建過程超詳細(xì)解析》,Spring 在第一次創(chuàng)建單例對象 B 的時候,會進(jìn)行屬性的填充,此時會調(diào)用工廠獲取 A 的多例對象。創(chuàng)建好 B 之后就將 B 緩存起來,下次獲取直接從緩存中獲取 B,拿到后直接返回,不會再次去工廠中獲取 A 對象了,所以這就是作用域失效的根本原因。
問題解決
要想解決此問題,我們需要延遲獲取多例對象。這里提供四種方案可供參考:
方案一:作用域指定代理
@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 都是獲取的代理的對象,只要在代理上調(diào)用方法,每次獲取都會根據(jù)作用域重新獲取。
方案二:指定懶加載
@Component
@Scope("prototype")
public class A {
}
@Component
public class B {
@Lazy
@Autowired
private A a;
@Override
public String toString() {
return "B{" +
"a=" + a +
'}';
}
}
使用懶加載一樣會創(chuàng)建代理的對象,只要在代理上調(diào)用方法,每次獲取都會根據(jù)作用域重新獲取。
方案三:使用對象工廠 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屬性失效問題的四種解決方案的詳細(xì)內(nèi)容,更多關(guān)于單例Bean注入多例失效的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
spring cloud學(xué)習(xí)入門之config配置教程
這篇文章主要給大家介紹了關(guān)于spring cloud學(xué)習(xí)入門之config配置的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用spring cloud具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。2017-09-09
基于java Springboot實(shí)現(xiàn)教務(wù)管理系統(tǒng)詳解
這篇文章主要介紹了Java 實(shí)現(xiàn)簡易教務(wù)管理系統(tǒng)的代碼,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-08-08
關(guān)于idea引入spring boot <parent></parent>父依賴標(biāo)紅問題
這篇文章主要介紹了idea引入spring boot <parent></parent>父依賴標(biāo)紅問題,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-10-10
Java前端Layer.open.btn驗(yàn)證無效解決方法
在本篇文章里我們給大家整理了一篇關(guān)于Java前端Layer.open.btn驗(yàn)證無效解決方法以及實(shí)例代碼,需要的朋友們可以參考學(xué)習(xí)下。2019-09-09
JDK內(nèi)置工具之常用工具和實(shí)戰(zhàn)指令詳解
jdk提供了很多強(qiáng)大的工具有命令行也有可視化的,這篇文章主要介紹了JDK內(nèi)置工具之常用工具和實(shí)戰(zhàn)指令的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2025-08-08

