How can I reload properties file in Spring 4 using annotations?

前端 未结 3 1620
死守一世寂寞
死守一世寂寞 2020-11-28 09:30

I have a simple application where i am using several properties-files to fetch content edited by other users (links to sites etc).

The class where i load the propert

相关标签:
3条回答
  • 2020-11-28 09:56

    the PropertyPlaceholderConfigurer need to be override to reload the new Properties

    You need to rewrite processProperties method to make the StringValueResolver which contains the properties became to loadable. This is my code

    import java.io.IOException;
    import java.util.Properties;
    import org.springframework.beans.BeansException;
    import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
    import org.springframework.beans.factory.config.PropertyPlaceholderConfigurer;
    import org.springframework.util.PropertyPlaceholderHelper;
    import org.springframework.util.PropertyPlaceholderHelper.PlaceholderResolver;
    import org.springframework.util.StringValueResolver;
    
    
    public class ReloadablePropertyPlaceholderConfigurer 
                                        extends PropertyPlaceholderConfigurer {
    
        private ReloadablePlaceholderResolvingStringValueResolver reloadableValueResolver;
    
    
        public void reloadProperties() throws IOException {
            Properties props = mergeProperties();
            this.reloadableValueResolver.refreshProperties(props);
        }
    
    
        @Override
        protected void processProperties(ConfigurableListableBeanFactory beanFactoryToProcess, Properties props)
                throws BeansException {
            this.reloadableValueResolver = new ReloadablePlaceholderResolvingStringValueResolver(props);
            StringValueResolver valueResolver = this.reloadableValueResolver;
            this.doProcessProperties(beanFactoryToProcess, valueResolver);
        }
    
    
        private class ReloadablePlaceholderResolvingStringValueResolver 
                implements StringValueResolver {
    
            private final PropertyPlaceholderHelper helper;
            private final ReloadablePropertyPlaceholderConfigurerResolver resolver;
    
            public ReloadablePlaceholderResolvingStringValueResolver(Properties props) {
                this.helper = new PropertyPlaceholderHelper(placeholderPrefix, placeholderSuffix, valueSeparator, ignoreUnresolvablePlaceholders);
                this.resolver = new ReloadablePropertyPlaceholderConfigurerResolver(props);
            }
    
            @Override
            public String resolveStringValue(String strVal) throws BeansException {
                String value = this.helper.replacePlaceholders(strVal, this.resolver);
                return (value.equals(nullValue) ? null : value);
            }
    
            private void refreshProperties(Properties props){
                this.resolver.setProps(props);
            }
        }
    
        private class ReloadablePropertyPlaceholderConfigurerResolver 
                implements PlaceholderResolver {
    
            private Properties props;
            private ReloadablePropertyPlaceholderConfigurerResolver(Properties props) {
                this.props = props;
            }
    
            @Override
            public String resolvePlaceholder(String placeholderName) {
                return ReloadablePropertyPlaceholderConfigurer.this.resolvePlaceholder(placeholderName, props, SYSTEM_PROPERTIES_MODE_FALLBACK);
            }
    
            public void setProps(Properties props) {
                this.props = props;
            }
       }
    }
    

    here is the configure for properties-config.xml .all of those properties can be reload in runtime as a prototype bean.

    <bean id="propertyConfigurer" class="com.cn21.mail189.analysis.commons.expand.ReloadablePropertyPlaceholderConfigurer">
        <property name="ignoreUnresolvablePlaceholders" value="true" />
        <property name="locations">
            <list>
                <!-- database config -->
                <value>classpath:spring/dbconfig.properties</value>
                <!-- app config -->
                <value>classpath:spring/app.properties</value>
                <!-- some other config -->
                <value>classpath:xxxx.properties</value>
            </list>
        </property>
    </bean>`
    
    0 讨论(0)
  • 2020-11-28 09:59

    Inside applicationContext.xml

    <bean id="beanId" 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>
    
    0 讨论(0)
  • 2020-11-28 10:04

    This works a treat. Requires Java 7, Apache commons logging, Apache commons lang (v2.6) and Apache commons Configuration:

    package corejava.reloadTest;
    
    import org.apache.commons.configuration.ConfigurationException;
    import org.apache.commons.configuration.PropertiesConfiguration;
    import org.apache.commons.configuration.reloading.FileChangedReloadingStrategy;
    
    public class MyApplicationProperties {
        private static PropertiesConfiguration configuration = null;
    
        static {
            try {
                configuration = new PropertiesConfiguration("test.properties");
            } catch (ConfigurationException e) {
                e.printStackTrace();
            }
            configuration.setReloadingStrategy(new FileChangedReloadingStrategy());
        }
    
        public static synchronized String getProperty(final String key) {
            return (String) configuration.getProperty(key);
        }
    }
    

    and test it with:

    package corejava.reloadTest;
    
    public class TestReloading {
        public static void main(String[] args) {
            while (true) {
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(MyApplicationProperties.getProperty("key"));
            }
        }
    }
    

    Output when you change test.properties is something like this (original contents of test.props was key=value, later changed to key=value1 mid-program execution):

    value
    value
    value
    value
    value
    Jan 17, 2015 2:05:26 PM org.apache.commons.configuration.PropertiesConfiguration reload
    INFO: Reloading configuration. URL is file:/D:/tools/workspace   /AutoReloadConfigUsingApacheCommons/resources/test.properties
    value1
    value1
    value1
    

    You could also consider Official Spring Framework Reference Documentation Refreshable beans , using a DSL like Groovy for this.

    0 讨论(0)
提交回复
热议问题