Spring技巧之動態讀取配置檔案
阿新 • • 發佈:2019-01-22
需求背景
最近碰到的需求大概是這樣,我們要在一個現有的專案基礎上進行二次開發,但又不願意碰原有專案裡的程式碼。所以採用了Maven依賴的方式——新建一個Maven專案作為主要開發環境,將原有專案作為Maven依賴(war形式)引入進來。這樣在新建的擴充套件專案中打包出來的war將會是合併兩個專案的所有程式碼。
而在實際搭建的過程中碰到這樣一個問題,Spring配置檔案中的 <context:property-placeholder />
只允許存在一個, 而且這個機會已經被原有專案使用了——這種說法並不嚴謹,所以以下給出三種解決方案:
方案一
以上關於<context:property-placeholder />
<!-- 如果要配置多個, 就要設定ignore-unresolvable ="true" -->
<context:property-placeholder location="classpath:extend/db.properties" ignore-unresolvable="true" />
<context:property-placeholder location="classpath:db.properties" ignore-unresolvable="true" />
但是這樣帶來的壞處就是:
1. 將發現錯誤的時機推遲到了執行時,這在系統比較龐大時實在是大忌。
2. 屬性重複時的替換危機,這種BUG想要找出來,耗費的時間和精力想想就不寒而慄。
方案二
第二個方法 就是BeanFactoryPostProcessor
介面,注意該介面的回撥時機早於佔位符替換 操作。
// BeanFactoryPostProcessor.postProcessBeanFactory
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
// 我們自己去讀取指定的配置檔案
Properties prop = null ;
try {
prop = PropertiesLoaderUtils.loadAllProperties("extend/db.properties", Thread.currentThread().getContextClassLoader());
} catch (IOException e) {
e.printStackTrace();
}
if(null == prop){
return;
}
// 注入到特定的Bean的特定屬性中
BeanDefinition beanDefinition = beanFactory.getBeanDefinition("dataSource_extend");
beanDefinition.getPropertyValues().add("url", prop.getProperty("db.sd.url"));
beanDefinition.getPropertyValues().add("driverClassName",prop.getProperty("db.sd.driverClassName"));
beanDefinition.getPropertyValues().add("username", prop.getProperty("db.sd.username"));
beanDefinition.getPropertyValues().add("password", prop.getProperty("db.sd.password"));
super.postProcessBeanFactory(beanFactory);
}
方案三
還有一種方法就是使用Spring的父子容器的關係,將這個 <context:property-placeholder/>
和依賴它的Bean全部註冊到一個全新容器中,然後將該容器作為現有容器的Parent。此方法過去取巧,本人沒有實際去嘗試。