Spring - 使用新的Property File值替换bean属性值

时间:2010-11-03 07:13:31

标签: java spring properties placeholder

我有一个属性文件并使用Spring属性占位符,我将值设置为Spring bean。现在,可以在运行时修改此属性文件。有没有办法用这个新修改的属性值刷新Spring bean的属性?特别是,我有很多单身豆?如何使用新值刷新它们?是否已有解决方案或是否应定制编码?如果它还不存在,有人可以提供最佳方法来实现这一目标吗?谢谢!

PS:我的应用程序是一个批处理应用程序。我使用基于Spring的Quartz配置来安排批次。

1 个答案:

答案 0 :(得分:3)

我会将此留待参考,但更新的答案位于分隔符下方:

ConfigurableApplicationContext接口包含refresh()方法,它应该是您想要的,但问题是:如何访问该方法。无论你采用哪种方式,你都会从一个具有ConfigurableApplicationContext类型依赖关系的bean开始:

private ConfigurableApplicationContext context;
@Autowired
public void setContext(ConfigurableApplicationContext ctx){
    this.context = ctx;
}

现在我建议的两个基本选项是

  1. 使用Task Execution Framework并让您的bean定期监视属性资源,在发现更改时刷新ApplicationContext或
  2. expose the bean to JMX,允许您手动触发刷新。

  3. 参考评论:由于似乎无法刷新整个上下文,因此另一种策略是创建属性工厂bean并将其注入所有其他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注入到所有其他bean中,但是,您必须小心始终使用原型范围。这在单例bean a solution can be found here中尤其棘手。

    如果你不想在整个地方注入查找方法,你也可以像这样注入一个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);
        }
    
    }