重新初始化spring @Autowire bean

时间:2018-10-04 22:22:09

标签: java spring autowired spring-bean

我有一个场景,我需要在启动期间根据应用程序配置来初始化bean。后来,由于基于事件获取了动态配置,因此我必须更新bean。

该bean无法更新,只能用新实例替换。

使用new运算符仅初始化本地实例还是会更改Bean?

@Component
public class TestComp {

  @Autowired
  private BeanA beanA;

  public void updateBean() {
    beanA = new BeanA("new value");
  }

}

我在另一个类中引用了该bean,并在用new对其进行了初始化之后进行了检查。它反映了新对象。但是,我需要得到专家的确认。

2 个答案:

答案 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获得的价值。