Spring 從核心而言,是一個(gè)DI 容器,其設計哲學(xué)是提供一種無(wú)侵入式的高擴展性框架。即無(wú)需代
碼中涉及Spring專(zhuān)有類(lèi),即可將其納入Spring容器進(jìn)行管理。
作為對比,EJB則是一種高度侵入性的框架規范,它制定了眾多的接口和編碼規范,要求實(shí)現者必須
遵從。侵入性的后果就是,一旦系統基于侵入性框架設計開(kāi)發(fā),那么之后任何脫離這個(gè)框架的企圖都將付
出極大的代價(jià)。
為了避免這種情況,實(shí)現無(wú)侵入性的目標。Spring 大量引入了Java 的Reflection機制,通過(guò)動(dòng)態(tài)
調用的方式避免硬編碼方式的約束,并在此基礎上建立了其核心組件BeanFactory,以此作為其依賴(lài)注入
機制的實(shí)現基礎。
org.springframework.beans包中包括了這些核心組件的實(shí)現類(lèi),核心中的核心為BeanWrapper
和BeanFactory類(lèi)。這兩個(gè)類(lèi)從技術(shù)角度而言并不復雜,但對于Spring 框架而言,卻是關(guān)鍵所在,如果
所謂依賴(lài)注入,即在運行期由容器將依賴(lài)關(guān)系注入到組件之中。
講的通俗點(diǎn),就是在運行期,由Spring根據配置文件,將其他對象的引用通過(guò)組件的提供的setter方法進(jìn)
行設定。
我們知道,如果動(dòng)態(tài)設置一個(gè)對象屬性,可以借助Java的Reflection機制完成:
Class cls = Class.forName("net.xiaxin.beans.User");
Method mtd = cls.getMethod("setName",new Class[]{String.class});
Object obj = (Object)cls.newInstance();
mtd.invoke(obj,new Object[]{"Erica"});
return obj;
上面我們通過(guò)動(dòng)態(tài)加載了User類(lèi),并通過(guò)Reflection調用了User.setName方法設置其name屬性。
出于簡(jiǎn)潔,我們將類(lèi)名和方法名都以常量的方式硬編碼。假設這些常量都是通過(guò)配置文件讀入,那我們就實(shí)現了一個(gè)最簡(jiǎn)單的BeanWrapper。這個(gè)BeanWrapper的功能很簡(jiǎn)單,提供一個(gè)設置JavaBean屬性的通用方法(Apache BeanUtils 類(lèi)庫中提供了大量針對Bean的輔助工具,如果有興趣可以下載一份源碼加以研讀)。
Spring BeanWrapper基于同樣的原理,提供了一個(gè)更加完善的實(shí)現。
看看如何通過(guò)Spring BeanWrapper操作一個(gè)JavaBean:
Object obj = Class.forName("net.xiaxin.beans.User").newInstance();
BeanWrapper bw = new BeanWrapperImpl(obj);
bw.setPropertyValue("name", "Erica");
System.out.println("User name=>"+bw.getPropertyValue("name"));
對比之前的代碼,相信大家已經(jīng)知道BeanWrapper的實(shí)現原理。
誠然,通過(guò)這樣的方式設定Java Bean屬性實(shí)在繁瑣,但它卻提供了一個(gè)通用的屬性設定機制,而這
樣的機制,也正是Spring依賴(lài)注入機制所依賴(lài)的基礎。
通過(guò)BeanWrapper,我們可以無(wú)需在編碼時(shí)就指定JavaBean的實(shí)現類(lèi)和屬性值,通過(guò)在配置文件
加以設定,就可以在運行期動(dòng)態(tài)創(chuàng )建對象并設定其屬性(依賴(lài)關(guān)系)。
上面的代碼中,我們僅僅指定了需要設置的屬性名“name”,運行期,BeanWrapper將根據Java
Bean規范,動(dòng)態(tài)調用對象的“setName”方法進(jìn)行屬性設定。屬性名可包含層次,如對于屬性名
“address.zipcode”,BeanWrapper會(huì )調用“getAddress().setZipcode”方法。
聯(lián)系客服