简体   繁体   中英

How to reload properties with Spring?

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.

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.

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

I would suggest replacing the java.util.Properties with a PropertiesConfiguration from the Apache Commons Configuration project. It supports automatic reloading, either by detecting when the file changes, or by triggering through JMX.

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.

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.

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

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.

<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.

Apache provide us utility to use reloadable properties file.

<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>

use apache common with spring as follow:

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

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/39998 Hot Reloading properties in Spring Boot and Java EE.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM