說說 Spring 的屬性編輯器

在 Spring 配置文件中遍尺,我們往往通過字面值設(shè)置 Bean 各種類型的屬性值 蔓同,這個功能是通過屬性編輯器實現(xiàn)的饶辙。

任何實現(xiàn)了 java.beans.PropertyEditor 接口的類都是屬性編輯器 。 它可以將外部需要設(shè)置的值轉(zhuǎn)換為 JVM 內(nèi)部的對應(yīng)類型斑粱,所以屬性編輯器其實就是一個類型轉(zhuǎn)換器 弃揽。

1 JavaBean 編輯器

Sun 所制定的 JavaBean 編輯器蹋宦,很大程度上是為 IDE 準(zhǔn)備的。它讓 IDE 能夠以可視化的方式來設(shè)置 JavaBean 的屬性 冷冗。

Java 通過 java.beans.PropertyEditor 定義了設(shè)置 JavaBean 屬性的方法惑艇,通過 BeanInfo 描述了 JavaBean 哪些屬性是可定制的,此外還描述了可定制屬性與 PropertyEditor 之間的對應(yīng)關(guān)系 滨巴。

BeanInfo 與 JavaBean 之間的對應(yīng)關(guān)系,通過兩者之間規(guī)范的命名確立泰偿,對應(yīng) JavaBean 的 BeanInfo 采用如下命名規(guī)范:<Bean>BeanInfo蜈垮。 如 BookBean 對應(yīng)的 BeanInfo 為 BookBeanBeanInfo。 當(dāng) JavaBean 連同其屬性編輯器注冊到 IDE 后调塌,當(dāng)在開發(fā)界面中對 JavaBean 進(jìn)行定制時惠猿, IDE 就會根據(jù) JavaBean 規(guī)范找到對應(yīng)的 BeanInfo ,然后再根據(jù) BeanInfo 中的描述信息找到 JavaBean 屬性描述(使用哪個屬性編輯器等),進(jìn)而為 JavaBean 生成特定開發(fā)編輯界面 政溃。

Java 提供了一個用于管理默認(rèn)屬性編輯器的管理器: PropertyEditorManager 檀葛,它保存著一些常見類型的屬性編輯器腹缩,如果某個 JavaBean 的常見類型屬性沒有通過 BeanInfo 顯式指定它的屬性編輯器, 那么 IDE 將自動使用 PropertyEditorManager 中注冊的對應(yīng)屬性的默認(rèn)編輯器 润讥。

1.1 屬性編輯器(PropertyEditor)

PropertyEditor 是屬性編輯器接口盘寡,它定義了將外部設(shè)置值轉(zhuǎn)換為內(nèi)部 JavaBean 屬性值的接口方法 。主要接口方法說明如下:

方法 說明
Object getValue() 返回屬性的當(dāng)前值 竿痰,基本類型被封裝成對應(yīng)的包裝類型
void setValue(Object newValue) 設(shè)置屬性的值,基本類型以包裝類型傳入
String getAsText() 用字符串來表示屬性對象影涉,以便外部的屬性編輯器能夠以可視化的方式顯示 。 默認(rèn)返回 null 匣缘,表示該屬性不能以字符串表示鲜棠。
void setAsText(String text) 用一個字符串去更新屬性的內(nèi)部值豁陆,它一般從外部屬性編輯器傳入的。
String[] getTags() 返回表示有效屬性值的字符串?dāng)?shù)組表鳍,以便屬性編輯器能夠以下拉框的方式進(jìn)行展示 里逆。 默認(rèn)返回 null。
String getJavaInitializationString() 為屬性提供初始值胁镐,屬性編輯器以此值作為屬性的默認(rèn)值 。

PropertyEditor 接口是內(nèi)部屬性值和外部設(shè)置值的溝通橋梁 盯漂。

Java 為 PropertyEditor 提供了一個方便的實現(xiàn)類: PropertyEditorSupport ,該類實現(xiàn)了 PropertyEditor 接口帖渠,我們可以通過擴(kuò)展這個類來設(shè)計自己的屬性編輯器 竭宰。

1.2 Bean 屬性描述(BeanInfo)

BeanInfo 描述了 JavaBean 中的可編輯屬性以及對應(yīng)的屬性編輯器,每一個屬性對應(yīng)一個屬性描述器 PropertyDescriptor狞甚。

PropertyDescriptor 的構(gòu)造函數(shù)有兩個入?yún)ⅲ?PropertyDescriptor(String propertyName, Class beanClass) 廓旬,其中 propertyName 為屬性名; beanClass 是 JavaBean 所對應(yīng)的 Class孕豹。

PropertyDescriptor 還有一個 setPropertyEditorClass(Class propertyEditorClass) 方法,它可以為 JavaBean 屬性指定編輯器 励背。

BeanInfo 接口中最重要的方法是:PropertyDescriptor[] getPropertyDescriptors() ,它會返回 JavaBean 的屬性描述器數(shù)組 终畅。

BeanInfo 接口的一個常用的實現(xiàn)類是 SimpleBeanInfo 竟闪,我們可以通過擴(kuò)展這個類來實現(xiàn)自定義的功能 。

2 Spring 默認(rèn)屬性編輯器

Spring 的屬性編輯器與傳統(tǒng)的用于 IDE 開發(fā)的屬性編輯器不同炼蛤,它沒有 UI 界面,只是將配置文件中的文本配置值轉(zhuǎn)換為 Bean 屬性的對應(yīng)值 絮识。

Spring 在 PropertyEditorRegistrySupport 中為常見的屬性類型提供了默認(rèn)屬性編輯器嗽上,分為 3 大類,共有 32 個:

類型 說明
基礎(chǔ)數(shù)據(jù)類型 【1】基本數(shù)據(jù)類型彼念,如: boolean、int 等逐沙; 【2】基本數(shù)據(jù)類型封裝類吩案,如: Boolean、Integer 等徘郭; 【3】基本數(shù)據(jù)類型數(shù)組: char[] 和 byte[] ; 【4】大數(shù): BigDecimal 和 BigInteger 捆毫。
集合類 Collection冲甘、Set途样、SortedSet、List 和 SortedMap何暇。
資源類 Class裆站、Class[]、File宏胯、InputStream、Locale杭棵、Properties氛赐、Resource[] 和 URL。

PropertyEditorRegistrySupport 中有兩個用于保存屬性編輯器的 Map 類型變量:

變量名 說明
defaultEditors 保存默認(rèn)屬性類型的編輯器滓侍,元素的鍵為屬性類型牲芋,值為對應(yīng)的屬性編輯器實例尔破。
customEditors 保存用戶自定義的屬性編輯器浇衬,元素的鍵值和 defaultEditors 相同 。

3 自定義 Spring 屬性編輯器

如果我們的應(yīng)用定義了特殊類型的屬性胆剧,并且希望在配置文件中以字面值方式來配置屬性值醉冤,那么就可以編寫自定義屬性編輯器并注冊到 Spring 容器的方式來實現(xiàn)。

Spring 默認(rèn)的屬性編輯器大都擴(kuò)展自 java.beans.PropertyEditorSupport蚁阳,我們可以通過擴(kuò)展 PropertyEditorSupport 來自定義屬性編輯器 。在Spring 環(huán)境下僅需要將配置文件中字面值轉(zhuǎn)換為屬性類型的對象即可颠悬,并不需要提供 UI 界面定血,所以僅需要覆蓋 PropertyEditorSupport 的 setAsText() 方法就可以啦 (∩_∩)O哈哈~。

假設(shè)我們有兩個實體 Book 和 Author灾票,希望在配置 Book 時茫虽,可以直接設(shè)置 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);

        //調(diào)用父類的方法悼枢,來設(shè)置屬性對象
        setValue(author);
    }
}

如果使用 BeanFactory ,則需要手工調(diào)用 registerCustomEditor(Class requiredType, PropertyEditor propertyEditor) 方法注冊自定義屬性編輯器莹妒;如果使用的是 ApplicationContext 绰上,那么只需要在配置文件中注冊 CustomEditorConfigurer 即可 。CustomEditorConfigurer 實現(xiàn)了BeanFactoryPostProcessor 接口蜈块,所以它是一個 Bean 的工廠后處理器 。

現(xiàn)在注冊自定義的屬性編輯器:

<!-- 注冊自定義的屬性編輯器-->
<bean class="org.springframework.beans.factory.config.CustomEditorConfigurer">
    <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" class="net.deniro.spring4.editor.Book">
    <property name="name" value="海邊的卡夫卡"/>
    <!-- 使用之前定義的編輯器注入該屬性-->
    <property name="author" value="村上春樹"/>
</bean>

BeanWrapper 在設(shè)置 book 的 author 屬性時课锌,將檢索自定義屬性編輯器注冊表,當(dāng)發(fā)現(xiàn) author 屬性類型所對應(yīng)的屬性編輯器 CustomPropertyEditor 時渺贤,它就會這個定制的屬性編輯器把 "村上春樹" 轉(zhuǎn)換為 Author 對象 。

按照規(guī)范瞭亮, Java 會在 JavaBean 的相同類包下查找是否存在 <JavaBean>Editor 的類固棚;如果存在,就會自動使用 <JavaBean>Editor作為該 JavaBean 的屬性編輯器 唆缴。Spring 也支持這個規(guī)范黍翎。


所以如果在類包下有一個名為 AuthorEditor 屬性編輯器類艳丛,那么就無須在配置文件中注冊自定義的屬性編輯器啦O(∩_∩)O哈哈~

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市碰酝,隨后出現(xiàn)的幾起案子戴差,更是在濱河造成了極大的恐慌,老刑警劉巖暖释,帶你破解...
    沈念sama閱讀 211,123評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件球匕,死亡現(xiàn)場離奇詭異,居然都是意外死亡橄杨,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,031評論 2 384
  • 文/潘曉璐 我一進(jìn)店門乡摹,熙熙樓的掌柜王于貴愁眉苦臉地迎上來采转,“玉大人,你說我怎么就攤上這事氏义。” “怎么了邻邮?”我有些...
    開封第一講書人閱讀 156,723評論 0 345
  • 文/不壞的土叔 我叫張陵克婶,是天一觀的道長情萤。 經(jīng)常有香客問我,道長筋岛,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,357評論 1 283
  • 正文 為了忘掉前任肪获,我火速辦了婚禮柒傻,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘青柄。我一直安慰自己预侯,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,412評論 5 384
  • 文/花漫 我一把揭開白布喇喉。 她就那樣靜靜地躺著校坑,像睡著了一般千诬。 火紅的嫁衣襯著肌膚如雪膏斤。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,760評論 1 289
  • 那天傲茄,我揣著相機(jī)與錄音沮榜,去河邊找鬼。 笑死蟆融,一個胖子當(dāng)著我的面吹牛型酥,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播弥喉,決...
    沈念sama閱讀 38,904評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼由境,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了虏杰?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,672評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎州弟,沒想到半個月后低零,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,118評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡啃奴,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,456評論 2 325
  • 正文 我和宋清朗相戀三年雄妥,在試婚紗的時候發(fā)現(xiàn)自己被綠了依溯。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片瘟则。...
    茶點(diǎn)故事閱讀 38,599評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡醋拧,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出丹壕,到底是詐尸還是另有隱情,我是刑警寧澤缭乘,帶...
    沈念sama閱讀 34,264評論 4 328
  • 正文 年R本政府宣布盏袄,位于F島的核電站,受9級特大地震影響逛尚,放射性物質(zhì)發(fā)生泄漏刁愿。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,857評論 3 312
  • 文/蒙蒙 一滤钱、第九天 我趴在偏房一處隱蔽的房頂上張望脑题。 院中可真熱鬧,春花似錦叔遂、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,731評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春蹬碧,著一層夾襖步出監(jiān)牢的瞬間履恩,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,956評論 1 264
  • 我被黑心中介騙來泰國打工飒筑, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留绽昏,地道東北人。 一個月前我還...
    沈念sama閱讀 46,286評論 2 360
  • 正文 我出身青樓全谤,卻偏偏與公主長得像,于是被迫代替她去往敵國和親认然。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,465評論 2 348

推薦閱讀更多精彩內(nèi)容