java 如何使用 Spring 重新加载属性?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13248066/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-31 12:01:24  来源:igfitidea点击:

How to reload properties with Spring?

javaspringproperties

提问by Julias

I'm using properties file with Spring 3. When Spring initializes its contex it loads the properties file and puts it in all beans with @Value annotation.

我在 Spring 3 中使用属性文件。当 Spring 初始化其上下文时,它会加载属性文件并将其放入所有带有 @Value 注释的 bean 中。

I want to have a possibility to update some properties in a file, and expose a JMX on the server that will reload the new properties to Spring - without restarting the server, and reloading its context.

我希望有可能更新文件中的某些属性,并在服务器上公开一个 JMX,该 JMX 会将新属性重新加载到 Spring - 无需重新启动服务器并重新加载其上下文。

Can I implement this by using some Spring methodto reload properties and populate them to all beans, or should I write something like this by my own?

我可以通过使用一些Spring 方法重新加载属性并将它们填充到所有 bean 来实现这一点,还是应该自己编写类似的东西?

采纳答案by Emmanuel Bourg

I would suggest replacing the java.util.Propertieswith a PropertiesConfigurationfrom the Apache Commons Configurationproject. It supports automatic reloading, either by detecting when the file changes, or by triggering through JMX.

我会建议更换java.util.PropertiesPropertiesConfigurationApache的共享配置项目。它支持自动重新加载,通过检测文件何时更改,或通过 JMX 触发。

回答by jdevelop

I think there is no common way of doing that. The most "clean" one would be to shut down the Spring context and build it from scratch. For example, consider using of DBCP connection pool and updating it's database connection URL. This means that the pool has to be properly shut down, then new object has to be created and then all references to the pool has to be updated as well. Now, some beans may take connection from that pool, and updating the pool config means that you need to re-request connections somehow. Thus, beans may need to know how to do that, which is not common.

我认为没有通用的方法可以做到这一点。最“干净”的方法是关闭 Spring 上下文并从头开始构建它。例如,考虑使用 DBCP 连接池并更新它的数据库连接 URL。这意味着必须正确关闭池,然后必须创建新对象,然后还必须更新对池的所有引用。现在,某些 bean 可能会从该池获取连接,更新池配置意味着您需要以某种方式重新请求连接。因此,bean 可能需要知道如何做到这一点,这并不常见。

I'd suggest to create separate bean with configuration and update events, and put that bean as dependency for all beans you need to know about configuration changes. Then you may use Apache Commons Configuration for waching file changes and propagate configuration updates.

我建议使用配置和更新事件创建单独的 bean,并将该 bean 作为您需要了解的有关配置更改的所有 bean 的依赖项。然后您可以使用 Apache Commons Configuration 来查看文件更改并传播配置更新。

Perhaps use JMS is good (if you later going distribute your app).

也许使用 JMS 是好的(如果您以后要分发您的应用程序)。

回答by Rajith Delantha

Yes you can do this in Spring JMX way. Add these beans to your spring config file. Create a separate method to read the property file. In this sample I use callThisAgain() method.

是的,您可以以 Spring JMX 的方式执行此操作。将这些 bean 添加到您的 spring 配置文件中。创建一个单独的方法来读取属性文件。在此示例中,我使用 callThisAgain() 方法。

<bean id="exporter" class="org.springframework.jmx.export.MBeanExporter">
    <property name="beans">
        <map>
            <entry key="your.package.bean:name=sampleBeanService" value-ref="sampleService"/>
        </map>
    </property>
    <property name="assembler">
        <bean class="org.springframework.jmx.export.assembler.MethodNameBasedMBeanInfoAssembler">
            <property name="managedMethods">
                <value>
                    callThisAgain <!--Simply declare the method name here (only the name) -->
                </value>
            </property>
        </bean>
    </property>
</bean>

<bean class="org.springframework.jmx.support.ConnectorServerFactoryBean" depends-on="rmiRegistry">
    <property name="objectName" value="connector:name=rmi"/>
    <property name="serviceUrl" value="service:jmx:rmi://127.0.0.1/jndi/rmi://127.0.0.1:11000/sample"/>
</bean>

<bean id="rmiRegistry" class="org.springframework.remoting.rmi.RmiRegistryFactoryBean">
    <property name="port" value="11000"/>
</bean>

After that you can use jconsole to reload your method without restarting server.

之后,您可以使用 jconsole 重新加载您的方法,而无需重新启动服务器。

回答by Mohit Singh

Apache provide us utility to use reloadable properties file.

Apache 为我们提供了使用可重载属性文件的实用程序。

<bean id="propertiesReloadingStrategy" class="org.apache.commons.configuration.reloading.FileChangedReloadingStrategy">
    <property name="refreshDelay" value="30000" /> <!-- 30 seconds -->
</bean>

<bean id="reloadableProperties" class="org.apache.commons.configuration.PropertiesConfiguration">
    <constructor-arg value="file:/web/${weblogic.Domain}/${weblogic.Name}/${app.Name}/reloadable_cfg/Reloadable.properties"/>
    <property name="reloadingStrategy" ref="propertiesReloadingStrategy"/>
</bean>

回答by David Hofmann

While some here are suggesting using an external way to use properties(external to Spring's own way of using property files). This answer is exactly what you are looking for https://stackoverflow.com/a/52648630/39998Hot Reloading properties in Spring Boot and Java EE.

虽然这里有些人建议使用外部方式来使用属性(在 Spring 自己的使用属性文件的方式之外)。这个答案正是您正在寻找的https://stackoverflow.com/a/52648630/39998Spring Boot 和 Java EE 中的热重载属性。

回答by M2E67

use apache common with spring as follow:

使用与 spring 通用的 apache 如下:

@Component
public class ApplicationProperties {
    private PropertiesConfiguration configuration;

    @PostConstruct
    private void init() {
        try {
            String filePath = "/opt/files/myproperties.properties";
            System.out.println("Loading the properties file: " + filePath);
            configuration = new PropertiesConfiguration(filePath);

            //Create new FileChangedReloadingStrategy to reload the properties file based on the given time interval
            FileChangedReloadingStrategy fileChangedReloadingStrategy = new FileChangedReloadingStrategy();
           fileChangedReloadingStrategy.setRefreshDelay(60*1000);
            configuration.setReloadingStrategy(fileChangedReloadingStrategy);
        } catch (ConfigurationException e) {
            e.printStackTrace();
        }
    }

    public String getProperty(String key) {
        return (String) configuration.getProperty(key);
    }

    public void setProperty(String key, Object value) {
        configuration.setProperty(key, value);
    }

    public void save() {
        try {
            configuration.save();
        } catch (ConfigurationException e) {
            e.printStackTrace();
        }
    }
}