Spring - 使用新的Property File值替换bean属性值 [英] Spring - Replacing the bean property values with new Property File values
问题描述
我有一个属性文件并使用Spring属性占位符,我将值设置为Spring bean。现在,可以在运行时修改此属性文件。有没有办法用这个新修改的属性值刷新Spring bean的属性?特别是,我有很多单身豆?如何使用新值刷新它们?是否已有解决方案或是否应该自定义编码?如果它还不存在,有人可以提供最佳方法来实现这一目标吗?谢谢!
I have a property file and using Spring property place holder, I set values to the Spring beans. Now, this property file may be modified during the run time. Is there a way to refresh the properties of the Spring beans with this newly modified property value? Especially, I have many singleton beans? How can I refresh them with the new values? Is there already a solution to this or should it be custom coded? If it doesn't already exist, can someone please give the best approach to achieve this? Thanks!
PS:我的应用程序是一个批处理应用程序。我使用基于Spring的Quartz配置来安排批次。
PS: My application is a batch application. I use Spring based Quartz configuration to schedule the batches.
推荐答案
我将把它留作参考,但更新的答案是在分隔符下面:
I'll leave this in for reference, but the updated answer is below the divider:
那么 ConfigurableApplicationContext
接口包含一个 refresh()方法,应该是什么你想要,但问题是:如何访问该方法。无论你采用哪种方式,你都会从一个依赖类型为 ConfigurableApplicationContext
的bean开始:
Well the ConfigurableApplicationContext
interface contains a refresh() method, which should be what you want, but the question is: how to access that method. Whichever way you do it, you'll start with a bean that has a dependency of type ConfigurableApplicationContext
:
private ConfigurableApplicationContext context;
@Autowired
public void setContext(ConfigurableApplicationContext ctx){
this.context = ctx;
}
现在我建议的两个基本选项是
Now the two basic options I'd suggest would be to either
- 使用任务执行框架让你的bean定期监视属性资源,在发现更改时刷新ApplicationContext或
- 将bean暴露给JMX ,允许您手动触发刷新。
- use the Task Execution Framework and let your bean watch the property resources regularly, refreshing the ApplicationContext when it finds changes or
- expose the bean to JMX, allowing you to manually trigger the refresh.
参考评论:自似乎无法刷新整个上下文,另一种策略是创建属性工厂bean并将其注入所有其他bean。
Referring to comments: since it seems impossible to refresh the entire context, an alternative strategy would be to create a properties factory bean and inject that into all other beans.
public class PropertiesFactoryBean implements FactoryBean<Properties>{
public void setPropertiesResource(Resource propertiesResource){
this.propertiesResource = propertiesResource;
}
private Properties value=null;
long lastChange = -1L;
private Resource propertiesResource;
@Override
public Properties getObject() throws Exception{
synchronized(this){
long resourceModification = propertiesResource.lastModified();
if(resourceModification != lastChange){
Properties newProps = new Properties();
InputStream is = propertiesResource.getInputStream();
try{
newProps.load(is);
} catch(IOException e){
throw e;
} finally{
IOUtils.closeQuietly(is);
}
value=newProps;
lastChange= resourceModification;
}
}
// you might want to return a defensive copy here
return value;
}
@Override
public Class<?> getObjectType(){
return Properties.class;
}
@Override
public boolean isSingleton(){
return false;
}
}
您可以将此属性bean注入但是,所有其他bean都必须小心,始终使用原型范围。这在单例bean中尤其棘手,可以在这里找到解决方案。
You could inject this properties bean into all your other beans, however, you would have to be careful to always use prototype scope. This is particularly tricky inside singleton beans, a solution can be found here.
如果你不喜欢我想在整个地方注入查找方法,你也可以像这样注入一个 PropertyProvider
bean:
If you don't want to inject lookup methods all over the place, you could also inject a PropertyProvider
bean like this:
public class PropertiesProvider implements ApplicationContextAware{
private String propertyBeanName;
private ApplicationContext applicationContext;
public void setPropertyBeanName(final String propertyBeanName){
this.propertyBeanName = propertyBeanName;
}
@Override
public void setApplicationContext(final ApplicationContext applicationContext) throws BeansException{
this.applicationContext = applicationContext;
}
public String getProperty(final String propertyName){
return ((Properties) applicationContext.getBean(propertyBeanName)).getProperty(propertyName);
}
}
这篇关于Spring - 使用新的Property File值替换bean属性值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!