通過${xxx}PropertyPlaceholderConfigurer動態加載superdiamond

由於某個項目需要讀取多個數據源,因此對每個數據源模塊創建一個xml文件

在applicationcontext.xml中<import>該xml,spring就能自動裝配。

之前有一個疑問${jdbc.password}是如何讀取superdiamond配置的呢?


首先,在applicationcontext.xml中

有這樣兩個bean

<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="properties" ref="propertiesConfiguration"/>
</bean>

<bean id="propertiesConfiguration" class="com.github.diamond.client.PropertiesConfigurationFactoryBean"/>

其中<bean id="propertiesConfiguration" class="com.github.diamond.client.PropertiesConfigurationFactoryBean"/>聲明的是superdiamond的配置文件。

PropertyPlaceholderConfigurer是BeanFactoryPostProcessor接口的一個實現。

 

PropertyPlaceholderConfigurer可以將上下文(配置文 件)中的屬性值放在另一個單獨的標準java Properties文件中去。在XML文件中用${key}替換指定的properties文件中的值。這樣的話,只需要對properties文件進 行修改,而不用對xml配置文件進行修改。

PropertyPlaceholderConfigurer的實例化過程:

Spring在啓動時會通過AbstractApplicationContext#refresh啓動容器初始化工作

會委託loadBeanDefinitions解析xml配置文件

loadBeanDefinitions找到DefaultBeanDefinitionDocumentReader#parseBeanDefinition解析具體的bean

這邊由於不是標準類定義,所以委託BeanDefinitionParserDelegate解析


通過id找到PropertyPlaceholderBeanDefinitionParser解析器解析

PropertySourcesPlaceholderConfigurer的繼承體系

  1. BeanFactoryPostProcessor
    定義一個用於修改容器中bean definition的屬性的接口.其實現類在一般類使用前先實例化,並對其他類的屬性進行修改.
    這跟BeanPostProcessor有明顯的區別,BeanPostProcessor是修改bean實例的.

  2. PropertiesLoaderSupport
    加載properties文件的抽象類.
    這邊具體的加載邏輯是委託PropertiesLoaderUtils#fillProperties實現

  3. PropertyResourceConfigurer
    bean definition中佔位符的替換就是這個抽象類實現的.
    實現BeanFactoryPostProcessor#postProcessBeanFactory,迭代容器的中的類定義,進行修改
    具體如何修改就通過鉤子processProperties交由子類實現

  4. PlaceholderConfigurerSupport
    使用visitor設計模式,通過BeanDefinitionVisitor和StringValueResolver更新屬性
    StringValueResolver是一個轉化String類型數據的接口,真正更新屬性的api實現竟然是在PropertyPlaceholderHelper#parseStringValue

  5. PropertySourcesPlaceholderConfigurer
    覆寫postProcessorBeanFactory api定義解析流程

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章