Реинициализировать весенний боб @Autowire

У меня есть сценарий, где мне нужно инициализировать компонент на основе конфигурации приложения во время запуска. Позже, из-за динамической конфигурации, извлекаемой на основе события, мне нужно обновить компонент.

Этот бин не может быть обновлен, но может быть заменен только новым экземпляром.

Использует ли new оператор инициализирует только локальный экземпляр или это изменит бин?

@Component
public class TestComp {

  @Autowired
  private BeanA beanA;

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

}

Я передал компонент в другом классе и проверил после того, как инициализировал его new, Это отражало новый объект. Но мне нужно подтверждение экспертов, если это произойдет.

2 ответа

У меня есть сценарий, где мне нужно инициализировать компонент на основе конфигурации приложения во время запуска.

Все в порядке. Прицел Singleton - хороший выбор здесь.

Позже, из-за динамической конфигурации, извлекаемой на основе события, мне нужно обновить компонент.

Это проблема. Обновление bean-компонента в контексте - сложный процесс: вам нужно удалить существующее определение bean-компонента, добавить новое и обновить все bean-компоненты, которые как-то связаны с bean-компонентом (повторно инициализировать эти компоненты, обновить контекст). Технически это возможно, и это было упрощено Spring Cloud @RefreshScope,

Использование оператора new инициализирует только локальный экземпляр, или это изменит бин?

Это влияет только на поле в этом классе. Никто не знает об изменениях. ApplicationContext#getBean still вернет старый объект, и все компоненты будут (или уже были) инициализированы со старым экземпляром.

Я передал bean-компонент в другой класс и проверил его после инициализации новым. Это отражало новый объект.

Это не может быть правдой. Вероятно, это относится к TestComp#beanA поле, а не себе BeanA поле.

Решение, которое я предлагаю, состоит в том, чтобы определить пользовательскую область действия bean-компонента на основе событий, которые вы получаете. Это будет держать бин и контекст обновленными.

Похоже, вы хотите фабрику вместо этого. Ниже приведено приблизительное представление о том, как это может выглядеть. Ваши потребности могут отличаться.

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

Затем вы подключаете его, и на основе конфигурации вы можете обновить и использовать новое значение. Имейте в виду, что это изменит значение, которое вы получите от этого компонента.

Другие вопросы по тегам