java - Spring - 用新的属性文件值替换 bean 属性值

标签 java spring properties placeholder

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

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

  1. 使用Task Execution Framework并让您的 bean 定期监视属性资源,在发现更改时刷新 ApplicationContext 或
  2. 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/

相关文章:

java - quartz + Spring : Configure jobs to run on specific time using JobStore

Java Bean 复合注入(inject)

C#动态改变对象的属性

Java 通用容器类

java - 如何覆盖从父复杂类型继承的元素类型?

java - 在常规 Java 中访问 JavaScript "window.confirm"的结果

java - 在 spring bean 的基类中定义的方法中使用 @Retryable 不会重试

java - Spring Integration - 占位符未注入(inject) ws :outbound-gateway uri (only for unit tests)

properties - 没有 setter 的属性的 TypeScript 接口(interface)签名。

c# - 是否有一个我可以在我的类中使用的属性来告诉 DataGridView 在绑定(bind)到 List<MyClass> 时不要为其创建列