Spring - замена значений свойств компонента на новые значения файла свойств - PullRequest
5 голосов
/ 03 ноября 2010

У меня есть файл свойств и, используя заполнитель свойств Spring, я устанавливаю значения для бинов Spring.Теперь этот файл свойств может быть изменен во время выполнения.Есть ли способ обновить свойства bean-компонентов Spring с помощью этого недавно измененного значения свойства?Особенно у меня много синглтон-бобов?Как я могу обновить их новыми значениями?Есть ли уже решение для этого или оно должно быть пользовательским?Если он еще не существует, может кто-нибудь дать лучший подход для достижения этого?Спасибо!

PS: Мое приложение является пакетным приложением.Я использую Spring Quartz конфигурацию для планирования партий.

1 Ответ

3 голосов
/ 03 ноября 2010

Я оставлю это для справки, но обновленный ответ находится ниже делителя:

Ну, а интерфейс ConfigurableApplicationContext содержит метод refresh () , который должен быть какимВы хотите, но вопрос в том, как получить доступ к этому методу.Как бы вы это ни делали, вы начнете с компонента, который имеет зависимость типа ConfigurableApplicationContext:

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

Теперь я бы предложил два основных варианта:

  1. используйте Framework Execution Framework и позволяйте вашему компоненту регулярно просматривать ресурсы свойств, обновляя ApplicationContext при обнаружении изменений или
  2. , предоставляя компоненту JMX , что позволяет вам вручную запускать обновление.

Ссылаясь на комментарии: поскольку кажется невозможным обновить весь контекст, альтернативной стратегией будет создание фабрики свойств и добавление ее ввсе остальные 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-компоненты, однако вам следует быть осторожным, чтобы всегда использовать область действия прототипа.Это особенно сложно внутри синглтон-бинов, решение можно найти здесь .

Если вы не хотите внедрять методы поиска повсеместно, вы также можете добавить PropertyProviderбоб, как это:

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);
    }

}
...