在Spring 配置文件中,我們往往通過字面值設置Bean 各種類型的屬性值,這個功能是通過屬性編輯器實現的。
任何實現了java.beans.PropertyEditor 接口的類都是屬性編輯器。 它可以將外部需要設置的值轉換為JVM 內部的對應類型,所以屬性編輯器其實就是一個類型轉換器。
1 JavaBean 編輯器
Sun 所製定的JavaBean 編輯器,很大程度上是為IDE 準備的。它讓IDE 能夠以可視化的方式來設置JavaBean 的屬性。
Java 通過java.beans.PropertyEditor 定義了設置JavaBean 屬性的方法,通過BeanInfo 描述了JavaBean 哪些屬性是可定制的,此外還描述了可定制屬性與PropertyEditor 之間的對應關係。
BeanInfo 與JavaBean 之間的對應關係,通過兩者之間規範的命名確立,對應JavaBean 的BeanInfo 採用如下命名規範:<Bean>BeanInfo。 如BookBean 對應的BeanInfo 為BookBeanBeanInfo。 當JavaBean 連同其屬性編輯器註冊到IDE 後,當在開發界面中對JavaBean 進行定制時, IDE 就會根據JavaBean 規範找到對應的BeanInfo ,然後再根據BeanInfo 中的描述信息找到JavaBean 屬性描述(使用哪個屬性編輯器等),進而為JavaBean 生成特定開發編輯界面。
Java 提供了一個用於管理默認屬性編輯器的管理器: PropertyEditorManager ,它保存著一些常見類型的屬性編輯器,如果某個JavaBean 的常見類型屬性沒有通過BeanInfo 顯式指定它的屬性編輯器, 那麼IDE 將自動使用PropertyEditorManager 中註冊的對應屬性的默認編輯器。
1.1 屬性編輯器(PropertyEditor)
PropertyEditor 是屬性編輯器接口,它定義了將外部設置值轉換為內部JavaBean 屬性值的接口方法。主要接口方法說明如下:
| 方法 | 說明 |
|---|---|
| Object getValue() | 返回屬性的當前值,基本類型被封裝成對應的包裝類型 |
| void setValue(Object newValue) | 設置屬性的值,基本類型以包裝類型傳入 |
| String getAsText() | 用字符串來表示屬性對象,以便外部的屬性編輯器能夠以可視化的方式顯示。 默認返回null ,表示該屬性不能以字符串表示。 |
| void setAsText(String text) | 用一個字符串去更新屬性的內部值,它一般從外部屬性編輯器傳入的。 |
| String[] getTags() | 返回表示有效屬性值的字符串數組,以便屬性編輯器能夠以下拉框的方式進行展示。 默認返回null。 |
| String getJavaInitializationString() | 為屬性提供初始值,屬性編輯器以此值作為屬性的默認值。 |
PropertyEditor 接口是內部屬性值和外部設置值的溝通橋樑。
Java 為PropertyEditor 提供了一個方便的實現類: PropertyEditorSupport ,該類實現了PropertyEditor 接口,我們可以通過擴展這個類來設計自己的屬性編輯器。
1.2 Bean 屬性描述(BeanInfo)
BeanInfo 描述了JavaBean 中的可編輯屬性以及對應的屬性編輯器,每一個屬性對應一個屬性描述器PropertyDescriptor。
PropertyDescriptor 的構造函數有兩個入參: PropertyDescriptor(String propertyName, Class beanClass) ,其中propertyName 為屬性名; beanClass 是JavaBean 所對應的Class。
PropertyDescriptor 還有一個setPropertyEditorClass(Class propertyEditorClass) 方法,它可以為JavaBean 屬性指定編輯器。
BeanInfo 接口中最重要的方法是:PropertyDescriptor[] getPropertyDescriptors() ,它會返回JavaBean 的屬性描述器數組。
BeanInfo 接口的一個常用的實現類是SimpleBeanInfo ,我們可以通過擴展這個類來實現自定義的功能。
2 Spring 默認屬性編輯器
Spring 的屬性編輯器與傳統的用於IDE 開發的屬性編輯器不同,它沒有UI 界面,只是將配置文件中的文本配置值轉換為Bean 屬性的對應值。
Spring 在PropertyEditorRegistrySupport 中為常見的屬性類型提供了默認屬性編輯器,分為3 大類,共有32 個:
| 類型 | 說明 |
|---|---|
| 基礎數據類型 | 【1】基本數據類型,如: boolean、int 等; 【2】基本數據類型封裝類,如: Boolean、Integer 等; 【3】基本數據類型數組: char[] 和byte[] ; 【4】大數: BigDecimal 和BigInteger 。 |
| 集合類 | Collection、Set、SortedSet、List 和SortedMap。 |
| 資源類 | Class、Class[]、File、InputStream、Locale、Properties、Resource[] 和URL。 |
PropertyEditorRegistrySupport 中有兩個用於保存屬性編輯器的Map 類型變量:
| 變量名 | 說明 |
|---|---|
| defaultEditors | 保存默認屬性類型的編輯器,元素的鍵為屬性類型,值為對應的屬性編輯器實例。 |
| customEditors | 保存用戶自定義的屬性編輯器,元素的鍵值和defaultEditors 相同。 |
3 自定義Spring 屬性編輯器
如果我們的應用定義了特殊類型的屬性,並且希望在配置文件中以字面值方式來配置屬性值,那麼就可以編寫自定義屬性編輯器並註冊到Spring 容器的方式來實現。
Spring 默認的屬性編輯器大都擴展自java.beans.PropertyEditorSupport,我們可以通過擴展PropertyEditorSupport 來自定義屬性編輯器。在Spring 環境下僅需要將配置文件中字面值轉換為屬性類型的對象即可,並不需要提供UI 界面,所以僅需要覆蓋PropertyEditorSupport 的setAsText() 方法就可以啦(∩_∩)O哈哈~。
假設我們有兩個實體Book 和Author,希望在配置Book 時,可以直接設置Author 的名字。
Book.java
public class Book { /** * 作者*/ private Author author; /** * 書名*/ private String name; //省略get/setter 方法}Author.java
public class Author { private String name; //省略get/setter 方法}首先,自定義author 的屬性編輯器:
public class CustomPropertyEditor extends PropertyEditorSupport { @Override public void setAsText(String text) throws IllegalArgumentException { if(text==null||text.length()==0){ throw new IllegalArgumentException("格式錯誤"); } Author author=new Author(); author.setName(text); //調用父類的方法,來設置屬性對象setValue(author); }}如果使用BeanFactory ,則需要手工調用registerCustomEditor(Class requiredType, PropertyEditor propertyEditor)方法註冊自定義屬性編輯器;如果使用的是ApplicationContext ,那麼只需要在配置文件中註冊CustomEditorConfigurer 即可。 CustomEditorConfigurer 實現了BeanFactoryPostProcessor 接口,所以它是一個Bean 的工廠後處理器。
現在註冊自定義的屬性編輯器:
<!-- 註冊自定義的屬性編輯器--><bean> <property name="customEditors"> <map> <!-- key:屬性類型;value:屬性編輯器--> <entry key="net.deniro.spring4.editor.Author" value="net.deniro.spring4.editor.CustomPropertyEditor" /> </map> </property></bean><bean id="book"> <property name="name" value="海邊的卡夫卡"/> <!-- 使用之前定義的編輯器注入該屬性--> <property name="author" value="村上春樹"/></bean>
BeanWrapper 在設置book 的author 屬性時,將檢索自定義屬性編輯器註冊表,當發現author 屬性類型所對應的屬性編輯器CustomPropertyEditor 時,它就會這個定制的屬性編輯器把"村上春樹" 轉換為Author 對象。
按照規範, Java 會在JavaBean 的相同類包下查找是否存在<JavaBean>Editor的類;如果存在,就會自動使用<JavaBean>Editor作為該JavaBean 的屬性編輯器。 Spring 也支持這個規範。
所以如果在類包下有一個名為AuthorEditor 屬性編輯器類,那麼就無須在配置文件中註冊自定義的屬性編輯器啦O(∩_∩)O哈哈~
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持武林網。