Spring核心——官配BeanFactoryPostProcessor

IoC功能擴展點這篇文章中介紹了BeanFactoryPostProcessor及其使用方法,本篇介紹Spring官方提供的典型BeanFactoryPostProcessor。java

佔位符參數替換——PropertyPlaceholderConfigurer

若是你的工程有不少配置內容放置到Java的標準配置文件*.properties中,當把Properties的內容整合到Spring中時就會用到PropertyPlaceholderConfigurer。PropertyPlaceholderConfigurer3個功能:git

  1. 將配置中${property-name}格式的佔位符換爲加載的*.properties文件中的內容。
  2. 將配置中${property-name}格式的佔位符替換爲環境變量systemProperties(System.getProperty(key))中的內容。
  3. 若是文件和環境中有相同的key,按照規則對數據進行合併。

基本使用方法

PropertyPlaceholderConfigurer繼承了配置BeanFactoryPostProcessor接口,在IoC開始初始化Bean以前修改對應BeanDefinition。在使用時咱們直接向容器添加一個PropertyPlaceholderConfigurer便可:spring

<!-- 啓用佔位符替換須要引入PropertyPlaceholderConfigurer -->
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <!-- 指定*.properties文件的路徑 -->
    <property name="locations" value="classpath:project/config.properties"/>
</bean>

<!-- 替換Bean中的內容 -->
<bean id="A" class="x.y.z.User">
    <property name="name" value="${user.name}"/>
    <property name="address" value="${user.address}"/>
    <property name="age" value="${user.age}"/>
</bean>

對應的config.properties文件中的內容:json

user.name='Alice'
user.address='China'
user.age=20

除了直接引入一個Bean,能夠經過全局上下文配置啓動這一項功能:bash

<context:property-placeholder location="classpath:project/config.properties"/>

設置環境變量加載行爲

前面說了PropertyPlaceholderConfigurer除了會用*.properties文件中的參數去替換佔位符的內容,還會使用環境變量(System.getProperty(key))中的參數去替換。若是一個參數在配置文件中和系統環境變量中都存在,那麼默認會使用*.properties中的參數來替換配置中的佔位符。能夠使用PropertyPlaceholderConfigurer::systemPropertiesMode來修改這個行爲。他接受3個參數:ide

  • PropertyPlaceholderConfigurer.SYSTEM_PROPERTIES_MODE_NEVER(0):從不加載環境變量中的參數。
  • PropertyPlaceholderConfigurer.SYSTEM_PROPERTIES_MODE_FALLBACK(1):優先使用*.properties文件中的變量,若是不存在再使用環境變量中的。
  • PropertyPlaceholderConfigurer.SYSTEM_PROPERTIES_MODE_OVERRIDE(2):優先使用環境變量中的參數。

能夠這樣設置:ui

<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <!-- 優先使用環境變量中的參數 -->
    <property name="systemPropertiesMode" value="2"/>
</bean>

動態設置參數&動態替換類

除了經過環境變量和*.properties配置文件引入參數,還能夠直接寫在XML的配置上:this

<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <!-- 加載資源文件位置 -->
    <property name="locations">
        <value>classpath:myProject/config.properties</value>
    </property>
    <!-- 動態添加配置參數 -->
    <property name="properties">
        <value>define.runtime.class=x.y.z.A</value>
    </property>
</bean>
<!-- 動態加載一個類 -->
<bean id="a" class="${define.runtime.class}"/>

上面XML配置還展現了一個動態裝載類的方法。spa

按命名規則注入——PropertyOverrideConfigurer

PropertyOverrideConfigurer就是在PropertyPlaceholderConfigurer的基礎上擴展了一些功能節約一些寫配置文件的時間。他能夠讓你沒必要在XML文件寫佔位符而直接注入數據。看下面的例子:code

經過<bean>標籤引入了PropertyOverrideConfigurer類,而後有一個獨立的User單例,以及將Cpu、Ram、Graphics單例組合到Pc中。

<beans>
    <!-- 引入PropertyOverrideConfigurer -->
    <bean class="org.springframework.beans.factory.config.PropertyOverrideConfigurer"> 
        <property name="locations" value="classpath:xml/configoverride/config.properties"/>
    </bean>
    <!-- 配置Bean之間的組合關係 -->
    <bean id="user" class="chkui.springcore.example.xml.configoverride.User" />
    <bean id="cpu" class="chkui.springcore.example.xml.configoverride.entity.Cpu" />
    <bean id="ram" class="chkui.springcore.example.xml.configoverride.entity.Ram" />
    <bean id="graphics" class="chkui.springcore.example.xml.configoverride.entity.Graphics" />
    <bean id="pc" class="chkui.springcore.example.xml.configoverride.entity.Pc">
        <property name="cpu" ref="cpu"/>
        <property name="ram" ref="ram"/>
        <property name="graphics" ref="graphics"/>
    </bean>
</beans>

對應的*.properties配置是這樣的:

user.name=Alice
user.address=china
user.age=20

pc.cpu.brand=AMD
pc.graphics.brand=Nvdia
pc.ram.brand=Kingston

Cpu類的結構:

package chkui.springcore.example.xml.configoverride.entity;
public class Cpu {
	private String brand;
	public String getBrand() {
		return brand;
	}
	public void setBrand(String brand) {
		this.brand = brand;
	}
}

這個時候PropertyOverrideConfigurer會根據容器中Bean的id或name來注入數據,好比*.properties配置中的"pc"就對應XML中的<bean id="pc">,接着pc中有一個域(成員變量)名爲cpu那麼它對應*.properties配置文件中"pc.cpu.",因此pc.cpu.brand=AMD的配置會告訴PropertyOverrideConfigurer向pc單例中的cpu實例的"brand"域注入數據"AMD"。

因此使用PropertyOverrideConfigurer運行以後,不須要在XML使用${property-name}這樣的參數它會按照id或name的結構注入數據,此時user.getName() == "Alice"。若是類的關係是這個多層的結構同樣能夠根據Properties的結構注入數據,例如 pc.getPc().getBrand() == "AMD"。

例子的可執行代碼見本人碼雲庫中configoverride包

相關文章
相關標籤/搜索