1. 程式人生 > >從原始碼分析Spring處理property-placeholder原理

從原始碼分析Spring處理property-placeholder原理

一、如何在Spring中將屬性檔案配置內容載入到環境中

1.1、在Spring的XML配置檔案中配置<context:property-placeholder/>,由於<context:property-placeholder/>名稱空間為

http://www.springframework.org/schema/context,通過名稱空間名與處理程式的對映關係(Sping中配置的關係在sping.handlers檔案中),

找到處理器http\://www.springframework.org/schema/context=org.springframework.context.config.ContextNamespaceHandler

1.2、在ContextNamespaceHandler中的init()函式中註冊了parser解析器this.registerBeanDefinitionParser("property-placeholder", new PropertyPlaceholderBeanDefinitionParser());

1.3、呼叫PropertyPlaceholderBeanDefinitionParser.parse()函式開始解析XML中配置的屬性

1.4、在PropertyPlaceholderBeanDefinitionParser.parse()函式中呼叫了AbstractSingleBeanDefinitionParser.parseInternal()函式構建

構建內部BeanDefinition,最後呼叫了AbstractPropertyLoadingBeanDefinitionParser.doParse()函式解析property-placeholder自定義的屬性

1.5、最後將構建好的BeanDefinition註冊到BeanDefinitionRegistry註冊中心中供Spring上下文使用


二、如何使用載入到環境中的配置

2.1、Spring通過BeanFactoryProcessor進行擴充套件,Spring提供了PropertyPlaceholderConfigurer(其實現了BeanFactoryPostProcessor)

在Bean建立前將佔位符使用配置檔案中的配置值替換

<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" 
        init-method="init" destroy-method="close">
    <property name="url" value="${jdbc.url}"/>
    <property name="username" value="${jdbc.username}"/>
    <property name="password" value="${jdbc.password}"/>

</bean>

或者

@Value("${spring_only}")

private String springOnly;

2.2、通過兩種方式注入

Bean方式:

單個配置檔案

<bean id="propertyConfigurer"class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
   <property name="location">
     <value>conf/sqlmap/jdbc.properties</value>
   </property>
    <property name="fileEncoding">
      <value>UTF-8</value>
    </property>
</bean>
多個配置檔案
<bean id="propertyConfigurer"class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">  
    <property name="locations">
        <list>
            <value>/WEB-INF/mail.properties</value>  
            <value>classpath: conf/sqlmap/jdbc.properties</value>//注意這兩種value值的寫法
     </list>
    </property>

</bean>

標籤方式:

<context:property-placeholder location="classpath*:/WEB-INF/mail.properties" />

今天一個問題困擾了我一下午,因此必須記錄下來

PropertyPlaceholderConfigurer類中的location、locations、localProperties分別為 Resource、Resource[]、Properties[]型別,

而XML中指定屬性值時卻是字串型別,一直都不知道Spring在什麼時候、通過哪種機制處理轉換的(將字串轉換成Resource、Resource[]、Properties[])

研究了很久發現Spring提供了一些系統的屬性編輯器(超類為PropertyEditorSupport),Spring在解析和賦值property時,會呼叫對應的編輯器處理

,且Spring會預設依據property的型別找對應的編輯器。比如Resource有對應的編輯器ResourceEditor,會將字串值轉換處理為Resource、Resource[]。

若想要改變預設的PropertyEditor,可以新增自定義的來覆蓋它。在新增時可以使用一個自動檢測的機制:也就是需要遵照一定的規則

具體的規則是:PropertyEditor類和標準的 JavaBeans在同一個包下,並且他們PropertyEditor的類名是JavaBeans的類名加上“Editor”,比如:

  1. publicclass ExoticTypeEditor extends PropertyEditorSupport {  
  2.     publicvoid setAsText(String text) {  
  3.         setValue(new ExoticType(text.toUpperCase()));  
  4.     }  
  5. }  

可以看到這個PropertyEditor就是遵照了以上的命名規則,並且和ExoticType放在同一個包中,所以無需額外的配置就可以得到下面的輸出:

ANAMEFOREXOTICTYPE

那麼若沒有符合以上規則的話,怎麼辦呢?可以通過org.springframework.beans.factory.config.CustomEditorConfigurer這個Bean來註冊

為這個Bean配置customEditors屬性,該屬性是一個Map,將我們需要註冊的PropertyEditors都注入到這個Map裡就可以了:

  1. <beanclass="org.springframework.beans.factory.config.CustomEditorConfigurer">
  2.     <propertyname="customEditors">
  3.         <map>
  4.             <entrykey="document.six.test.ExoticType"value="document.six.test.ExoticType2Editor"/>
  5.         </map>
  6.     </property>
  7. </bean>