Как загрузить файл свойств в Spring 4 с помощью аннотаций?
У меня есть простое приложение, в котором я использую несколько свойств файлов для извлечения контента, отредактированного другими пользователями (ссылки на сайты и т.д.).
Класс, в котором я загружаю свойства, выглядит следующим образом:
@Configuration
@PropertySource("classpath:salestipsWhitelist.properties")
public class SalestipsWhitelist {
@Autowired
Environment env;
public Environment getEnv() {
return env;
}
public void setEnv(Environment env) {
this.env = env;
}
@Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
}
Некоторые из файлов свойств:
UPS_MPP_M_L=True
UPS_MPP_M_M=True
UPS_MPP_M_MP=True
UPS_MPP_M_S=True
Это отлично работает, но если я вношу изменения в файл свойств, я должен перезагрузить приложение, чтобы визуализировать сделанные изменения.
Возможно ли, если я переместлю местоположение на диск вместо classpath, перезагружать его периодически или вручную? Я не хочу, чтобы это было сделано автоматически при изменении, так как я хочу контролировать, когда это будет сделано/обновлено.
Ответы
Ответ 1
Это работает. Требуется ведение журналов Java 7, Apache, Apache commons lang (v2.6) и общие настройки Apache Конфигурация:
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);
}
}
и протестируйте его с помощью:
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"));
}
}
}
Вывод при смене test.properties - это что-то вроде этого (исходное содержимое test.props было ключевым = значение, позже изменено на выполнение команды mid = value1):
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
Вы также можете рассмотреть Официальную Spring справочную документацию по Framework Refreshable beans, используя DSL, например Groovy.
Ответ 2
PropertyPlaceholderConfigurer необходимо переопределить для перезагрузки новых свойств
Вам нужно переписать метод processProperties
, чтобы сделать StringValueResolver
, который содержит свойства, которые стали загружаемыми.
Это мой код
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;
}
}
}
вот конфигурация для properties-config.xml
. Все эти свойства можно перезагрузить во время выполнения в качестве прототипа 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>`
Ответ 3
Внутри 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>