Java 未填充spring单例bean字段
我需要一个带有一些内部字段的服务(singleton fits),比如一个挂起线程的列表(是的,所有内容都是为了线程安全而编写的)。问题是,如果我Java 未填充spring单例bean字段,java,spring,Java,Spring,我需要一个带有一些内部字段的服务(singleton fits),比如一个挂起线程的列表(是的,所有内容都是为了线程安全而编写的)。问题是,如果我@autowire这个bean,字段似乎是空的。调试时,我看到代理使用填充的字段正确绑定到实例(字段CGLIB$CALLBACK\X正确链接到填充的bean),但它提供的字段是空的 下面几行代码概括了我所说的内容 @Service public class myService{ @Autowired private Monitor mon
@autowire
这个bean,字段似乎是空的。调试时,我看到代理使用填充的字段正确绑定到实例(字段CGLIB$CALLBACK\X
正确链接到填充的bean),但它提供的字段是空的
下面几行代码概括了我所说的内容
@Service
public class myService{
@Autowired
private Monitor monitor;
public List getSomething(){
return monitor.getList();
}
}
@Service
public class myStatefulService{
//This field will be populated for sure by someone before getSomething() is called
private List list;
public synchronized List getSomething(){
return this.list;
}
//Called by other services that self inject this bean
public synchronized void addToList(Object o){
this.list.add(o);
}
}
在getList调用期间调试变量monitor
monitor => instance of correct class
fields:
CGLIB$BOUND => true
CGLIB$CALLBACK_0.advised => proxyFactory (correct)
CGLIB$CALLBACK_1.target (reference to the correct instance of myStatefulService class)
fields:
list => [.........] (correctly populated)
CGLIB$CALLBACK_2 .....
......
......
......
list => [] (the list that would be populated is empty instead)
“在调用getSomething()之前,此字段肯定会有人填充”
有人吗?不,是春豆厂。如果不进行配置,则不会填充任何内容
并不是每个豆子都需要在春天的控制之下。听起来您希望有一个列表
,客户端可以通过线程安全的方式向其中添加和删除项目。如果是这样,请删除@Autowired
注释,创建一个新的列表
,并公开要添加和删除的方法
我推荐一份新的并发收藏列表。你是好奇还是有什么真正的问题?然而,这里有一个解释 当使用CGLIB代理类时,Spring将创建一个子类,名为
myService$enhancerbyglib
。这个增强的类将覆盖一些(如果不是全部的话)业务方法,以便围绕实际代码应用横切关注点
真正的惊喜来了。这个额外的子类不调用基类的super
方法。相反,它创建了myService
的第二个实例并委托给它。这意味着您现在有两个对象:您的真实对象和指向(包装)它的CGLIB增强对象
增强的类只是一个虚拟代理。它仍然具有与基类(继承自基类)相同的字段,但未使用这些字段。当您在myService$enhancerbyglib
对象上调用addToList()
时,它将首先应用一些AOP逻辑,调用myService
的addToList()
(它包装了它),并在返回时应用剩余的AOP逻辑。myService$EnhancerByGlib.list字段从未被触动过
为什么Spring不能通过
super
使用相同的类和委托?为了简单起见:首先创建“原始”bean,然后在后处理期间应用AOP代理。CGLIB将代理受保护的getter
因此,您可以:
@Autowired
private Monitor monitor;
protected Monitor getMonitor() { return monitor; }
public List getSomething(){
return getMonitor().getList();
}
getMonitor()将被代理,以便在已注入monitor的另一个实例上调用getMonitor()。抱歉,列表中的@autowired是一个键入错误。。。。一切都在Spring控件的控制之下,“某人”是响应客户端操作的另一个服务。。。因此,客户端使用其他服务将元素添加到列表中。带有列表的服务包含逻辑,并且定期在列表上工作,因此我需要是一个单例可注入有状态bean=),是的,我提供了向列表添加元素的方法,但是当读取列表时,如果代理指向的实例已正确填充,则列表也是空的。为什么需要代理?我想说,这是一个不需要受Spring控制的对象的示例。只需实例化一个新的,然后继续。提到
super
就救了我一天!我花了几个小时试图弄清楚为什么调用我的基类而不是增强版,直到我意识到调用程序调用了一个从基类本身传递回来的对的引用,这显然是行不通的。