简体   繁体   中英

Reinitialize spring @Autowire bean

I have a scenario where I need to initialize a bean based on application configuration during startup. Later, due to dynamic configuration fetched based on an event, I have to update the bean.

This bean can't be updated but can only be replaced with a new instance.

Does using the new operator initialize only the local instance or will it change the bean?

@Component
public class TestComp {

  @Autowired
  private BeanA beanA;

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

}

I referred the bean in another class and checked after I initialized it with new . It reflected the new object. But, I need a confirmation from experts if it does.

I have a scenario where I need to initialize a bean based on application configuration during startup.

It's fine. The singleton scope is a good choice here.

Later, due to dynamic configuration fetched based on an event, I have to update the bean.

It's a problem. Updating a bean in the context is a complex process: you need to remove the existing bean definition, add a new one, and update all the beans that are somehow related to the bean (reinitialise these components, refresh the context). Technically, it's possible and it has been simplified by Spring Cloud's @RefreshScope .

Does using new operator initialize only the local instance or will it change the bean?

It affects only the field in this class. No one is aware of the change. ApplicationContext#getBean still will return the old object, and all the components will be (or have already been) initialised with the old instance.

I referred the bean in another class and checked after I initialized it with new. It reflected the new object.

It can't be true. Probably, it refers to the TestComp#beanA field, not to its own BeanA field.

The solution I am suggesting is to define a custom bean scope based on the events you are receiving. It will keep the bean and the context updated.

It sounds like you want a factory instead . Below is a rough idea of what that might look like; your needs may vary.

@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);
        }
    }
}

You then wire this in, and based on configuration, you can then refresh and use the new value. Bear in mind that this would change the value you get from this bean.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM