【spring源碼深度解析—容器的功能擴展之initPropertySources】 ApplicationContext提供了更多的擴展功能。BeanFactory是容器的頂層接口類,ApplicationContext實現了BeanFactory所有功能同時增強了接口實現和功能擴展。大多數情況下優先使用ApplicationContext,
對 BeanFactory接口做了很多封裝了功能實現。
initPropertySources擴展功能說明
refresh函數中是spring核心,包含大部分ApplicationContext中提供的功能,代碼如下:
@Override public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { /** * 1、設置容器啟動時間 * 2、設置活躍狀態為true * 3、設置關閉狀態為false * 4、獲取Environment對象,並加載當前系統的屬性值到Environment對象中 * 5、准備監聽器和時間的集合對象,默認為空的集合 */ prepareRefresh(); …… } } /** * prepareRefresh 方法 */ protected void prepareRefresh() { // 設置容器啟動的時間 this.startupDate = System.currentTimeMillis(); // 容器的關閉標志位 this.closed.set(false); // 容器的激活標志位 this.active.set(true); // 記錄日志 if (logger.isDebugEnabled()) { if (logger.isTraceEnabled()) { logger.trace("Refreshing " + this); } else { logger.debug("Refreshing " + getDisplayName()); } } // 預留接口,便於子類功能擴展 initPropertySources(); // 1、檢查是否存在環境變量如果存在直接用,不存在重更新獲取 // 2、創建並獲取環境對象、驗證需要的屬性文件是否符合 getEnvironment().validateRequiredProperties(); // 判斷刷新前的應用程序監聽器集合是否為空,如果為空,則將監聽器添加到此集合中 if (this.earlyApplicationListeners == null) { this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners); } else { // 如果不等於空,則清空集合元素對象 this.applicationListeners.clear(); this.applicationListeners.addAll(this.earlyApplicationListeners); } // 創建刷新前的監聽事件集合 this.earlyApplicationEvents = new LinkedHashSet<>(); }
initPropertySources擴展功能說明
initPropertySources方法符合Spring的開放式結構設計,給用戶增加擴展Spring的能力。用戶可以根據自身的需要重寫initPropertySourece方法,並在方法中進行個性化設計及其業務處理。getEnvironment().validateRequiredProperties()中,validateRequiredProperties則是對屬性進行驗證。下面對這個屬性進行擴展舉例說明:
例增加如下需求:在項目運行過程中想通過系統環境變量中取得定義的某個值或者系統中的值操作。此需求有很多解決辦法,例如修改:spring原碼,在Spring提供我們很好擴展性,例如可通過實現initPropertySources擴展接口實現。實例代碼如下
/** * @author :java.zhao * @description:擴展initPropertySource,測試入口類 * @date :2018-10-08 15:23 */ public class testSuperInitPropertySources { /** * 演示:通過此例子可對系統的預留方法進行功能擴展,本次實現方法:【initPropertySources】 */ @Test public void test01() { MyClassPathXmlApplicatonContext ac1 = new MyClassPathXmlApplicatonContext("classpath:beanfactory.xml"); // ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring-${username}.xml"); System.out.println(ac1.getEnvironment().getSystemProperties().get("java.spring.teacher")); } }
/** * @author :java.zhao * @description:集成接口類,自定義類TycoonClassPathXmlApplicatonContext * @date :2018-10-08 15:19 */ public class TycoonClassPathXmlApplicatonContext extends ClassPathXmlApplicationContext { TycoonClassPathXmlApplicatonContext (String... configlocations){ super(configlocations); } // TODO 擴展 initPropertySources 方法,baidu實現 @Override protected void initPropertySources(){ // 還可以對系統屬性值進行,修改(特別注意,如果不存在此屬性程序會終止) //getEnvironment().setRequiredProperties("properties.error"); // 通過以上測試可得,可以對存在系統參數和內部環境變量等進行修改 System.out.println("擴展initPropertySource"); //這里添加了一個name屬性到Environment里面,以方便我們在后面用到 getEnvironment().getSystemProperties().put("java.spring.teacher","java.zhao"); // 此處我們做了兩個擴展: // 第一,向Environment中添加了一個屬性值。 // 第二:設置了一個必要的系統屬性properties.error,當Environment中不包含 // properties.error屬性時系統會拋出異常,程序會終止。 } }
輸出:
擴展initPropertySource
設置系統:java.spring.teacher 值為:java.zhao
Process finished with exit code 0