1. 程式人生 > >深入分析Spring屬性編輯器(預設屬性編輯器和自定義屬性編輯器)

深入分析Spring屬性編輯器(預設屬性編輯器和自定義屬性編輯器)

在Spring配置檔案或配置類裡,我們往往通過字面值為Bean各種型別的屬性提供設定值:不管是double型別還是int型別,在配置檔案中都對應字串型別的字面值。BeanWrapper填充Bean屬性時如何將這個字面值轉換為對應的double或int等內部型別呢?我們可以隱約地感覺到一定有一個轉換器在其中起作用,這個轉換器就是屬性編輯器。

一、 PropertyEditor

PropertyEditor是屬性編輯器的介面,它規定了將外部設定值轉換為內部JavaBean屬性值的轉換介面方法。PropertyEditor主要的介面方法說明如下: 
· Object getValue():返回屬性的當前值。基本型別被封裝成對應的封裝類例項; 
· void setValue(Object newValue):設定屬性的值,基本型別以封裝類傳入; 
· String getAsText():將屬性物件用一個字串表示,以便外部的屬性編輯器能以視覺化的方式顯示。預設返回null,表示該屬性不能以字串表示; 
· void setAsText(String text):用一個字串去更新屬性的內部值,這個字串一般從外部屬性編輯器傳入; 
· String[] getTags():返回表示有效屬性值的字串陣列(如boolean屬性對應的有效Tag為true和false),以便屬性編輯器能以下拉框的方式顯示出來。預設返回null,表示屬性沒有匹配的字元值有限集合; 
· String getJavaInitializationString():為屬性提供一個表示初始值的字串,屬性編輯器以此值作為屬性的預設值。

可以看出PropertyEditor介面方法是內部屬性值和外部設定值的溝通橋樑。此外,我們可以很容易地發現該介面的很多方法是專為IDE中的視覺化屬性編輯器提供的:如getTags()、getJavaInitializationString()以及另外一些我們未此介紹的介面方法。

PropertyEditorSupport

Java為PropertyEditor提供了一個方便類:PropertyEditorSupport,該類實現了PropertyEditor介面並提供預設實現,一般情況下,使用者可以通過擴充套件這個方便類設計自己的屬性編輯器。

二、 Spring內建屬性編輯器

        Spring框架內建了一些PropertyEditor來對,並且bean填充屬性之前都會把這些PropertyEditor新增到BeanWrapper中(在

Spring IOC容器bean初始化原始碼分析有分析),程式碼在PropertyEditorRegistrySupport類的createDefaultEditors方法中:

例項化Bean並使用BeanWrapper包裝Bean例項後,呼叫initBeanWrapper(),在此方法中檢查AbstractBeanFactory的變數propertyEditorRegistrars是否註冊了PropertyEditorRegistrar(ResourceEditorRegistrar在Spring載入並重新整理容器時,註冊至propertyEditorRegistrars屬性),執行註冊的PropertyEditorRegistrar.registerCustomEditors(),同時將自定義的屬性編輯器註冊至

PropertyEditorRegistrySupport.customEditors(BeanWrapperImpl繼承了PropertyEditorRegistrySupport)屬性中




此外還內建了一些Resource相關的PropertyEditor,程式碼在ResourceEditorRegistrar類的registerCustomEditors方法中:

AbstractApplicationContext.refresh()-->prepareBeanFactory()中註冊了ResourceEditorRegistrar




PropertyEditorRegistry屬性編輯器註冊

這個介面可以註冊和儲存屬性編輯器


PropertyEditorRegistrySupport

PropertyEditorRegistrySupport是PropertyEditorRegistry 預設實現類 ,PropertyEditorRegistrySupport中有兩個用於儲存屬性編輯器的Map型別變數defalutEditors和customEditors

BeanWrapperImpl實現了PropertyEditorRegistrySupport


Spring使用了懶註冊的方式,在通過屬性型別獲取編輯器時,當預設的屬性編輯器註冊變數defaultEditors為Null時,再呼叫

createDefaultEditors()註冊預設的屬性編輯器


Spring註冊的預設屬性編輯器清單詳見createDefaultEditors()函式中程式碼處理


三、 自定義屬性編輯器的註冊及查詢使用

CustomEditorConfigurer.postProcessBeanFactory()-->ConfigurableListableBeanFactory.registerCustomEditor()

1、spring中的屬性編輯器

Spring大部分預設屬性編輯器都直接擴充套件於java.beans.PropertyEditorSupport類,使用者也可以通過擴充套件PropertyEditorSupport實現自己的屬性編輯器。比起用於IDE環境的屬性編輯器來說,Spring環境下使用的屬性編輯器的功能非常單一:僅需要將配置檔案中字面值轉換為屬性型別的物件即可,並不需要提供UI介面,因此僅需要簡單覆蓋PropertyEditorSupport的setAsText()方法就可以了


2、註冊自定義屬性編輯器

   使用ApplicationContext,只需要在配置檔案中通過CustomEditorConfigurer註冊即可。CustomEditorConfigurer實現了BeanFactoryPostProcessor介面,因而是一個Bean工廠後置處理器,在Spring容器中載入配置檔案並生成BeanDefinition後會被執行。CustomEditorConfigurer在容器啟動時有機會註冊自定義的屬性編輯器


AbstractBeanFactory Bean工廠中提供了customEditors自定義編輯器註冊清單儲存


呼叫了CustomEditorConfigurer中的postProcessBeanFactory()方法,會將配置的自定義編輯器註冊至

AbstractBeanFactory中的customEditors儲存器中



編輯器註冊後,在使用時通過findCustomEditor()指定屬性型別,查詢預設和自定義屬性編輯器將字面量的值轉換為屬性定義的

型別物件