我有一个场景,我需要在启动期间根据应用程序配置来初始化bean。后来,由于基于事件获取了动态配置,因此我必须更新bean。
该bean无法更新,只能用新实例替换。
使用new
运算符仅初始化本地实例还是会更改Bean?
@Component
public class TestComp {
@Autowired
private BeanA beanA;
public void updateBean() {
beanA = new BeanA("new value");
}
}
我在另一个类中引用了该bean,并在用new
对其进行了初始化之后进行了检查。它反映了新对象。但是,我需要得到专家的确认。
答案 0 :(得分:2)
我有一个场景,我需要在启动期间根据应用程序配置来初始化bean。
很好。这里的单例作用域是一个不错的选择。
后来,由于基于事件获取了动态配置,因此我必须更新bean。
有问题。在上下文中更新bean是一个复杂的过程:您需要删除现有的bean定义,添加一个新的bean定义,并更新与该bean某种程度上相关的所有bean(重新初始化这些组件,刷新上下文)。从技术上讲,这是可能的,并且已由Spring Cloud的@RefreshScope
进行了简化。
使用new运算符仅初始化本地实例还是会更改Bean?
它仅影响此类中的字段。没有人知道这一变化。 ApplicationContext#getBean
仍将返回旧对象,并且所有组件都将(或已经)用旧实例初始化。
我在另一个类中引用了该bean,并在用new对其进行初始化之后进行了检查。它反映了新对象。
这不是真的。可能是指TestComp#beanA
字段,而不是它自己的BeanA
字段。
根据您收到的事件,我建议的解决方案是to define a custom bean scope。它将保持Bean和上下文的更新。
答案 1 :(得分:1)
听起来您想代替工厂 。下面是大概的样子。您的需求可能会有所不同。
@Component
public class BeanFactory {
private volatile BeanA beanAInstance;
public BeanA createBeanA(String value) {
if (null == beanAInstance) {
synchronized (this) {
if (null == beanAInstance) {
beanAInstance = new BeanA(value);
}
}
}
return beanAInstance;
}
public void refreshBeanA(String newValue) {
synchronized (this) {
beanAInstance = new BeanA(newValue);
}
}
}
然后将其连接,然后根据配置,可以刷新并使用新值。请记住,这将改变您从该bean获得的价值。