Spring - 使用新的Property File值替换bean属性值 [英] Spring - Replacing the bean property values with new Property File values

查看:197
本文介绍了Spring - 使用新的Property File值替换bean属性值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个属性文件并使用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


  1. 使用任务执行框架让你的bean定期监视属性资源,在发现更改时刷新ApplicationContext或

  2. 将bean暴露给JMX ,允许您手动触发刷新。

  1. use the Task Execution Framework and let your bean watch the property resources regularly, refreshing the ApplicationContext when it finds changes or
  2. 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆