在spring单例对象中使用多例对象

前话

需要在一个单例对象A中使用多例成员变量B。

如果仅仅在多例中加上@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE),由于A是一个单例,所以无论如何B都是一个单例。

背景

在单例A中有一个B类成员变量,B类通过@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE, proxyMode = ScopedProxyMode.TARGET_CLASS)注解标注这个类在A中是一个多例实现。这时候即使A是一个单例,B也会是一个多例。B中定义了一个initA(…)方法,初始化了B的成员变量,最终返回this。接着再次调用A的test()方法。

伪代码如下:

@Component
public class A {
@Autowire
B b;
}
public void test01() {
B b1 = b.initA(...);// 返回this
b1.test();// 发现调用test的时候,调用对象并不是上一步返回的this,而是重新得到的一个对象,因此导致对象没有初始化,得到错误的结果
}

分析

加了注解proxyMode = ScopedProxyMode.TARGET_CLASS后,通过源码跟踪发现每次调用B类中的方法时,触发AOP机制,将this用一个新对象替换掉了,导致最终调用initA(…)得到的对象和调用test()的对象不是同一个,导致后面新的对象没有经过初始化,执行逻辑就会有问题。

小结一下
不加proxyMode = ScopedProxyMode.TARGET_CLASS注解,单单使用@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)导致在单例A中B也一直是单例,因为A只初始化一次。

加入proxyMode = ScopedProxyMode.TARGET_CLASS本质上加入了AOP机制,对B类的方法调用前,都会创建新的对象,这就导致了无法使用同一个对象连续两次调用B类方法。

解决方案

B类使用@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)注解标注,那怎么解决B一直是个单例的问题呢?

在A类中不使用@Autowire自动注入的方式,而是使用ApplicationContext.getBean()的方式,这样每次getBean都得到一个新的对象b2,b2.init(…).test()完成程序的正常调用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值