Spring:如何进行透明运行时可更改属性配置

时间:2012-04-02 09:52:49

标签: spring configuration properties

Spring有一个很好的机制PropertyPlaceholderConfigurer,用于将值,例如timeouts,JDBC Urls等注入Spring bean以进行配置。是否有一种合理的方法来处理可在运行时更改的配置值?

更新:使用Spring 3.1,有一种很好的方法可以通过PropertySource包含非静态配置源,例如数据库。一些ApplicationContexts提供了一种原则上能够处理不断变化的配置值的刷新机制。然而,它首先停止应用程序,然后创建所有bean新鲜,然后再次启动应用程序上下文。但是,出于我们的目的,我需要一种方法来透明地执行此操作,以便服务器正确处理当前正在运行的请求。

执行此操作的另一个想法是在配置更改时创建新对象的自定义Scope。遗憾的是,提供给Scope的ObjectFactory使用了预处理的bean定义,因此不会从配置中重新读取占位符。因此,创建的对象具有相同的配置。 : - (

4 个答案:

答案 0 :(得分:2)

不幸的是,来自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 Using Source-Level Metadata (JDK 5.0 annotations)

答案 1 :(得分:2)

以下是有点奇怪但有效。您创建一个名为reconfigurable的{​​{3}},只要发生配置更新,就会抛弃在该范围内创建的所有bean。因此,在配置更改后将创建一个新bean。

必须通过spring表达式语言检索实际配置值,因为普通$ {}语法和PropertyOverrideConfigurer的值似乎都在BeanDefinition中永久修复。具有可重新配置属性someProperty的bean的bean声明如下所示:

<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 :(得分:1)

有一个正在运行的例子,说明你要在这里完成的任务:https://github.com/ldojo/spring-cloud-config-examples

它演示了Spring Cloud Config Server和客户端服务如何通过Spring Cloud Bus进行通信,并且当Config Server的repo中发生配置更改时,客户端的配置属性可以在运行时更改。

答案 3 :(得分:0)

对于有效的运行时重新配置,您可以使用spring的Cloud Config项目。在这种安排中,您将拥有一个Configuration Repository,比如一个git存储库,其中包含您的配置值。然后将Configuration Server放在该存储库的前面。只要对支持存储库发生推送,就会更新此服务器。最后,您的应用程序将是Config Server的客户端,并从中获取新的配置。查看Spring Cloud了解详情。