Могу ли я изменить параметры пружины при выполнении?

У меня есть приложение, которое использует динамических потребителей. Я использую Spring Framework с RabbitMQ.

У меня есть такие параметры, как concurrentConsumers и maxConcurrentConsumers.

Вот пример:

@Bean 
public SimpleMessageListenerContainer container(ConnectionFactory connection) {
    SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();

    container.setMaxConcurrentConsumers(8);
    container.setConcurrentConsumers(1);

    return container;
}

Могу ли я изменить значения во время работы приложения? Например, если я хочу 5 maxConcurrentConsumers вместо 8, могу ли я изменить значение на терминале или что-то подобное во время работы приложения?


person Maverick94    schedule 12.12.2018    source источник
comment
Разве вы не можете использовать аннотацию @Value и определить значения для concurrentConsumers и maxConcurrentConsumers в файле свойств, а затем предоставить метод установки для обновления этих значений во время выполнения? См. stackoverflow. com/questions/38761781/   -  person FakirTrappedInCode    schedule 12.12.2018
comment
Вы можете попробовать использовать аннотацию @RefreshScope с @Value примером: здесь вам нужно добавить приводы, а затем вы можете изменить свой файл свойств и вызвать /actuator/refresh   -  person Andrii Vdovychenko    schedule 12.12.2018
comment
@FakirTrappedInCode, но я должен остановить службу, изменить значения в файле свойств и снова запустить. Вы имели в виду это?   -  person Maverick94    schedule 12.12.2018
comment
@Spara да, но нет. Я просто меняю эти значения maxConcurrentConsumers и concurrentConsumers во время выполнения. Я думаю, что решение для ссылки немного сложное.   -  person Maverick94    schedule 12.12.2018
comment
как сказано в ссылке, вы можете изменить maxConcurrentConsumers во время выполнения, и он обновит значение в весеннем контексте для вас   -  person Spara    schedule 12.12.2018


Ответы (1)


Ваш bean-компонент является синглтоном и должен быть без состояния (по крайней мере, неизменным или фактически без состояния), чтобы обеспечить потокобезопасность и правильность.

Как правило, вы должны использовать область прототипа для всех bean-компонентов с состоянием и область singleton для bean-компонентов без сохранения состояния.

Spring документация

Иногда создание bean-компонента обходится довольно дорого, поэтому более разумно создать экземпляр один раз, а затем гарантировать, что все возможные изменения, сделанные в этом объекте, будут безопасным и правильным образом распространяться на всех его потребителей.

Я советую построить простой механизм, управляемый событиями.

Есть

  • MessageListenerContainerEvent extends ApplicationEvent, который представляет изменения, внесенные в bean-компонент MessageListenerContainer;
  • MessageListenerContainerChanger implements ApplicationListener<MessageListenerContainerEvent>, который является единственным слушателем, который изменяет состояние бина и гарантирует, что все работает правильно;
  • другие слушатели, которые используют этот компонент и заинтересованы в его обновлении. Нет необходимости отправлять изменения потребителям bean-компонентов, вы можете просто уведомить их без сообщения. Для них это означает, что некоторые свойства компонента, который они используют локально, могут быть устаревшими.
  • издатель, который может быть конечной точкой HTTP, или @ShellMethod.

Это может показаться слишком сложным, вы всегда можете упростить его до

// somewhere in your code
synchronized(bean) {
    bean.setConcurrentConsumers(10);
}

но имейте в виду правильность этого фрагмента.

person Andrew Tobilko    schedule 12.12.2018