|
Spring 從核心而言,是一個DI 容器,其設(shè)計哲學(xué)是提供一種無侵入式的高擴展性框架。即無需代 碼中涉及Spring專有類,即可將其納入Spring容器進(jìn)行管理。 作為對比,EJB則是一種高度侵入性的框架規(guī)范,它制定了眾多的接口和編碼規(guī)范,要求實現(xiàn)者必須 遵從。侵入性的后果就是,一旦系統(tǒng)基于侵入性框架設(shè)計開發(fā),那么之后任何脫離這個框架的企圖都將付 出極大的代價。 為了避免這種情況,實現(xiàn)無侵入性的目標(biāo)。Spring 大量引入了Java 的Reflection機制,通過動態(tài) 調(diào)用的方式避免硬編碼方式的約束,并在此基礎(chǔ)上建立了其核心組件BeanFactory,以此作為其依賴注入 機制的實現(xiàn)基礎(chǔ)。 org.springframework.beans包中包括了這些核心組件的實現(xiàn)類,核心中的核心為BeanWrapper 和BeanFactory類。這兩個類從技術(shù)角度而言并不復(fù)雜,但對于Spring 框架而言,卻是關(guān)鍵所在,如果
所謂依賴注入,即在運行期由容器將依賴關(guān)系注入到組件之中。 講的通俗點,就是在運行期,由Spring根據(jù)配置文件,將其他對象的引用通過組件的提供的setter方法進(jìn) 行設(shè)定。 我們知道,如果動態(tài)設(shè)置一個對象屬性,可以借助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; 上面我們通過動態(tài)加載了User類,并通過Reflection調(diào)用了User.setName方法設(shè)置其name屬性。 出于簡潔,我們將類名和方法名都以常量的方式硬編碼。假設(shè)這些常量都是通過配置文件讀入,那我們就實現(xiàn)了一個最簡單的BeanWrapper。這個BeanWrapper的功能很簡單,提供一個設(shè)置JavaBean屬性的通用方法(Apache BeanUtils 類庫中提供了大量針對Bean的輔助工具,如果有興趣可以下載一份源碼加以研讀)。 Spring BeanWrapper基于同樣的原理,提供了一個更加完善的實現(xiàn)。 看看如何通過Spring BeanWrapper操作一個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的實現(xiàn)原理。 誠然,通過這樣的方式設(shè)定Java Bean屬性實在繁瑣,但它卻提供了一個通用的屬性設(shè)定機制,而這 樣的機制,也正是Spring依賴注入機制所依賴的基礎(chǔ)。 通過BeanWrapper,我們可以無需在編碼時就指定JavaBean的實現(xiàn)類和屬性值,通過在配置文件 加以設(shè)定,就可以在運行期動態(tài)創(chuàng)建對象并設(shè)定其屬性(依賴關(guān)系)。 上面的代碼中,我們僅僅指定了需要設(shè)置的屬性名“name”,運行期,BeanWrapper將根據(jù)Java Bean規(guī)范,動態(tài)調(diào)用對象的“setName”方法進(jìn)行屬性設(shè)定。屬性名可包含層次,如對于屬性名 “address.zipcode”,BeanWrapper會調(diào)用“getAddress().setZipcode”方法。 |
|
|