Spring: как сделать прозрачную настройку изменяемого свойства во время выполнения - PullRequest
6 голосов
/ 02 апреля 2012

Spring имеет приятный механизм PropertyPlaceholderConfigurer для введения значений, таких как тайм-ауты, URL-адреса JDBC и т. Д., В bean-компоненты Spring для настройки.Есть ли разумный способ обработки значений конфигурации, которые могут изменяться во время выполнения?

ОБНОВЛЕНИЕ: В Spring 3.1 есть хороший способ включить нестатические источники конфигурации, такие как база данных, через PropertySource s.Некоторые ApplicationContexts предоставляют механизм обновления, который в принципе способен обрабатывать изменяющиеся значения конфигурации.Однако сначала он останавливает приложение, затем создает все новые компоненты и затем снова запускает контекст приложения.Однако для наших целей мне понадобится способ сделать это прозрачно, чтобы сервер правильно обрабатывал текущие запросы.

Еще одна идея сделать это - создать пользовательский Scope, который создает свежие объекты при изменении конфигурации.К сожалению, ObjectFactory, предоставляемая Scope, использует предварительно обработанное определение компонента, так что заполнители не считываются заново из конфигурации.Таким образом, созданные объекты имеют одинаковую конфигурацию.: - (

Ответы [ 4 ]

2 голосов
/ 23 апреля 2012

Следующее немного странно, но работает.Вы создаете пользовательскую область с именем reconfigurable, которая выбрасывает все компоненты, созданные в этой области, при каждом обновлении конфигурации.Таким образом, свежий бин будет создан после изменения конфигурации.

Фактические значения конфигурации должны быть получены с помощью языка выражений Spring, поскольку значения как для обычного синтаксиса $ {}, так и для PropertyOverrideConfigurer, по-видимому, постоянно фиксируются вBeanDefinition.Объявление bean-компонента для bean-компонента с переконфигурируемым свойством someProperty выглядит следующим образом:

<bean class="blablu.Testbean" scope="reconfigurable"
  p:someProperty="#{ config['configexplicit']}">
  <aop:scoped-proxy />
</bean>

Вам необходимо использовать aop: scoped-proxy, чтобы bean-компоненты, использующие этот bean-компонент, всегда получали самый свежий сконфигурированный bean-компонент.из пользовательской области.

Объявление свойств с помощью @Value также работает;если вы используете компонентное сканирование, вам нужно объявить область с аннотацией

@Scope(value="reconfigurableScope", proxyMode=ScopedProxyMode.TARGET_CLASS)

Если вам нужны подробности: основная идея области:

public class ReconfigurableScope implements Scope {

    private final Map<String, Object> nameToObjectMap = new ConcurrentHashMap<String, Object>();

    public Object get(final String name, final ObjectFactory<?> objectFactory) {
        Object bean = nameToObjectMap.get(name);
        if (null == bean) {
            bean = objectFactory.getObject();
            nameToObjectMap.put(name, bean);
        }
        return bean;
    }

    // called from outside on each configuration change
    public void update(final ConfigurationObservable observable, final Object arg) {
        nameToObjectMap.clear();
    }

}

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

2 голосов
/ 02 апреля 2012

К сожалению, конфигурация из файлов properties является статической и происходит при запуске.Что я обычно делаю, так это выставляю динамические атрибуты через :

@ManagedResource
@Service
public class BusinessService {

    @ManagedAttribute
    private int age;

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public void businessMethod() {
        //use age...
    }

}

Не забудьте добавить:

<context:mbean-export/>

В вашу конфигурацию.Теперь вы можете получить доступ к этому атрибуту и ​​изменить его с помощью jconsole или любого другого клиента JMX.См. Также: 23.3.2 Использование метаданных на уровне источника (аннотации JDK 5.0) .

1 голос
/ 08 марта 2016

Вот пример того, чего вы пытаетесь достичь: https://github.com/ldojo/spring-cloud-config-examples

Он демонстрирует, как Spring Cloud Config Server и клиентская служба могут обмениваться данными через Spring Cloud Bus, а свойства конфигурации клиента могут изменяться во время выполнения при изменении конфигурации в репозитории Config Server.

0 голосов
/ 19 августа 2015

Для эффективной реконфигурации времени выполнения вы можете использовать проект Spring Config. В этом случае у вас будет Configuration Repository, скажем, git-репозиторий, содержащий ваши значения конфигурации. Затем поместите Configuration Server перед этим хранилищем. Этот сервер будет обновляться всякий раз, когда происходит резервное копирование в резервное хранилище. Наконец, ваши приложения будут клиентами этого Config Server и получат из него новые конфиги. Проверьте Spring Cloud для более подробной информации.

...