由於某個項目需要讀取多個數據源,因此對每個數據源模塊創建一個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的繼承體系
-
BeanFactoryPostProcessor
定義一個用於修改容器中bean definition的屬性的接口.其實現類在一般類使用前先實例化,並對其他類的屬性進行修改.
這跟BeanPostProcessor有明顯的區別,BeanPostProcessor是修改bean實例的. -
PropertiesLoaderSupport
加載properties文件的抽象類.
這邊具體的加載邏輯是委託PropertiesLoaderUtils#fillProperties實現 -
PropertyResourceConfigurer
bean definition中佔位符的替換就是這個抽象類實現的.
實現BeanFactoryPostProcessor#postProcessBeanFactory,迭代容器的中的類定義,進行修改
具體如何修改就通過鉤子processProperties交由子類實現 -
PlaceholderConfigurerSupport
使用visitor設計模式,通過BeanDefinitionVisitor和StringValueResolver更新屬性
StringValueResolver是一個轉化String類型數據的接口,真正更新屬性的api實現竟然是在PropertyPlaceholderHelper#parseStringValue -
PropertySourcesPlaceholderConfigurer
覆寫postProcessorBeanFactory api定義解析流程