我有一个属性文件并使用 Spring 属性占位符,我将值设置为 Spring bean。现在,这个属性文件可以在运行时被修改。有没有办法用这个新修改的属性值来刷新 Spring bean 的属性?特别是,我有很多单例 bean ?我怎样才能用新值刷新它们?是否已经有解决方案或者应该自定义编码?如果它尚不存在,有人可以提供实现此目标的最佳方法吗?谢谢!
PS:我的申请是批量申请。我使用基于 Spring 的 Quartz 配置来安排批处理。
最佳答案
我会将其留作引用,但更新后的答案在分隔符下方:
ConfigurableApplicationContext
接口(interface)包含一个 refresh()方法,这应该是你想要的,但问题是:如何访问该方法。无论采用哪种方式,您都将从一个具有 ConfigurableApplicationContext
类型依赖项的 bean 开始:
private ConfigurableApplicationContext context;
@Autowired
public void setContext(ConfigurableApplicationContext ctx){
this.context = ctx;
}
现在我建议的两个基本选项是要么
- 使用Task Execution Framework并让您的 bean 定期监视属性资源,在发现更改时刷新 ApplicationContext 或
- expose the bean to JMX ,允许您手动触发刷新。
引用评论:由于刷新整个上下文似乎是不可能的,因此另一种策略是创建一个属性工厂 bean 并将其注入(inject)到所有其他 bean 中。
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 注入(inject)到所有其他 bean 中,但是,您必须小心始终使用原型(prototype)作用域。这在单例 bean 中特别棘手,a solution can be found here .
如果你不想到处注入(inject)查找方法,你也可以像这样注入(inject)一个 PropertyProvider
bean:
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);
}
}
关于java - Spring - 用新的属性文件值替换 bean 属性值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4084890/