春 - Beanプロパティ値を新しいプロパティファイル値に置き換える
-
28-09-2019 - |
質問
プロパティファイルがあり、Spring Property Place Holderを使用して、Spring Beanに値を設定します。これで、このプロパティファイルは実行時に変更される場合があります。この新しく変更されたプロパティ値でスプリングビーンズのプロパティを更新する方法はありますか?特に、私は多くのシングルトンビーンズを持っていますか?新しい値でそれらを更新するにはどうすればよいですか?すでにこれに対する解決策はありますか、それともカスタムコード化されるべきですか?それがまだ存在していない場合、誰かがこれを達成するために最良のアプローチを与えてください。ありがとう!
PS:私のアプリケーションはバッチアプリケーションです。バッチをスケジュールするために、スプリングベースのクォーツ構成を使用しています。
解決
参照のためにこれを残しますが、更新された回答は分裂者の下にあります。
さて ConfigurableApplicationContext
インターフェイスにはaが含まれます REFRESH() 方法は、あなたが望むものであるはずですが、問題は次のとおりです。その方法にアクセスする方法。どちらの方法でも、タイプの依存性を持つ豆から始めます ConfigurableApplicationContext
:
private ConfigurableApplicationContext context;
@Autowired
public void setContext(ConfigurableApplicationContext ctx){
this.context = ctx;
}
今、私が提案する2つの基本的なオプションはどちらかです
- 使用 タスク実行フレームワーク そして、あなたの豆に定期的にプロパティリソースを見てもらい、ApplicationContextが変更されたときにリフレッシュしてください。
- 豆をJMXに露出させます, 、リフレッシュを手動でトリガーできるようにします。
コメントを参照する:コンテキスト全体を更新することは不可能であるように思われるため、別の戦略は、プロパティファクトリーの豆を作成し、それを他のすべての豆に注入することです。
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;
}
}
このプロパティを他のすべての豆に注入することはできますが、常にプロトタイプスコープを使用するように注意する必要があります。これはシングルトンビーンズ内の特にトリッキーです、 解決策はここにあります.
あちこちにルックアップ方法を注入したくない場合は、 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);
}
}