背景:項目中使用了common-configuration庫用於加載配置文件,並經過擴展的ConfigManager實現統一的配置管理。 java
現象:考慮到有些配置信息能夠經過熱加載的方式,不用重啓服務器進行更新。commons-configuration提供了ReloadingStrategy和ConfigurationListener,示例代碼以下,經過RELOAD事件作實時的屬性更新操做,然而系統跑起來以後,修改文件並未監控到該事件的產生。 apache
PropertiesConfiguration config = new PropertiesConfiguration(configFile); FileChangedReloadingStrategy strategy = new FileChangedReloadingStrategy(); config.setReloadingStrategy(strategy); config.addConfigurationListener(new ConfigurationListener() { @Override public void configurationChanged(ConfigurationEvent e) { System.out.println("配置文件更新..."+e.getType()); if(PropertiesConfiguration.EVENT_RELOAD ==e.getType()) { System.out.println("配置文件重載..."); } } });
分析:首先排除apache的弱智,在該段代碼後,起一個獨立線程,每隔1秒打印一下目標屬性的值,看是否成功reload。結果發現不只成功reload,ConfigurationEvent也產生的,Changed執行了,什麼鬼?去掉線程後,又是老樣子。網上搜索毫無結果,最後只能到apache官網找緣由,並最終找到以下描述: FileChangedReloadingStrategy works as follows: On every property access the configuration checks its associated reloading strategy.
竟然是在屬性訪問的時候才check?要不訪問那listener不就毫無用處?!access的時候重載不還要作併發控制,要加鎖,雖然配置文件讀一下很快,不也影響體驗? 服務器
解決方案:
1.X版本只能本身另外建立個線程調用get方法以觸發property的access,進而觸發configurationChanged。
2.X版本新增了一個PeriodicReloadingTrigger來解決此問題,它會起一個ScheduledExecutorService,經過線程方式來處理 併發