Spring - Java/J2EE Application Framework 应用框架 第 8 章 源代码级的元数据支持
第?8?章?源代碼級(jí)的元數(shù)據(jù)支持
8.1.?源代碼級(jí)的元數(shù)據(jù)
源代碼級(jí)的元數(shù)據(jù)是對(duì)程序元素:通常為類和/或方法的?attribute?或者叫annotation的擴(kuò)充。
舉例來說,我們可以象下面一樣給一個(gè)類添加元數(shù)據(jù):
/*** Normal comments* @@org.springframework.transaction.interceptor.DefaultTransactionAttribute()*/ public class PetStoreImpl implements PetStoreFacade, OrderService {我們也可以添加元數(shù)據(jù)到一個(gè)方法上:
/*** Normal comments* @@org.springframework.transaction.interceptor.RuleBasedTransactionAttribute ()* @@org.springframework.transaction.interceptor.RollbackRuleAttribute (Exception.class)* @@org.springframework.transaction.interceptor.NoRollbackRuleAttribute ("ServletException")*/ public void echoException(Exception ex) throws Exception {.... }這兩個(gè)例子都使用了Jakarta Commons Attributes的格式。
源代碼級(jí)的元數(shù)據(jù)隨著Microsoft的.NET平臺(tái)的發(fā)布被介紹給大眾,它使用了源代碼級(jí)的attribute 來控制事務(wù),緩沖池(pooling)和一些其他的行為。
這種方法的價(jià)值已經(jīng)被J2EE社區(qū)的人們認(rèn)識(shí)到了。舉例來說,跟EJB中清一色使用的傳統(tǒng)的XML部署描述文 件比起來它要簡(jiǎn)單很多。XML描述文件適合于把一些東西從程序源代碼中提取出來,一些重要的企業(yè)級(jí)設(shè) 定——特別是事務(wù)特性——本來屬于程序代碼。并不像EJB規(guī)范中設(shè)想的那樣,調(diào)整一個(gè)方法的事務(wù)特性根本 沒有什么意義。
雖然元數(shù)據(jù)attribute主要用于框架的基礎(chǔ)架構(gòu)來描述應(yīng)用程序的類需要的業(yè)務(wù), 但是也可以在運(yùn)行時(shí)查詢?cè)獢?shù)據(jù)attribute。這是與XDoclet這樣的解決方案的關(guān)鍵區(qū)別,XDoclet 主要把元數(shù)據(jù)作為生成代碼的一種方式,比如生成EJB類。
這一段包括了幾個(gè)解決方案:
-
JSR-175:標(biāo)準(zhǔn)的Java元數(shù)據(jù)實(shí)現(xiàn),在Java 1.5中提供。 但是我們現(xiàn)在就需要一個(gè)解決方案,通常情況下可能還需要一個(gè)外觀(facade)。
-
XDoclet:成熟的解決方案,主要用于代碼生成
-
其它不同的開源attribute實(shí)現(xiàn),在JSR-175的發(fā)布 懸而未決的情況下,它們當(dāng)中的Commons Attributes看來是最有前途的。所有的這些實(shí)現(xiàn)都需要一 個(gè)特定的前編譯或后編譯的步驟。
8.2.?Spring的元數(shù)據(jù)支持
為了與它提供的其他重要概念的抽象相一致,Spring提供了一個(gè)對(duì)元數(shù)據(jù)實(shí)現(xiàn)的外觀(facade), 以org.springframework.metadata.Attributes這個(gè)接口的形式來表示。
這樣一個(gè)外觀很有價(jià)值,因?yàn)橄旅鎺讉€(gè)原因:
-
目前還沒有一個(gè)標(biāo)準(zhǔn)的元數(shù)據(jù)解決方案。 Java 1.5版本會(huì)提供一個(gè),但是在Spring1.0版本的時(shí)候, Java 1.5仍是beta版本。而且,至少兩年內(nèi)還是需要對(duì)1.3和1.4版本的應(yīng)用程序提供元數(shù)據(jù)支持。?現(xiàn)在Spring打算提供一些可以工作的解決方案: 在一個(gè)重要的環(huán)境下等待1.5,并不是個(gè)好的選擇.
-
目前的元數(shù)據(jù)API,例如Commons Attributes(被Spring 1.0使用), 測(cè)試起來很困難。Spring提供了一個(gè)簡(jiǎn)單的更容易模擬的元數(shù)據(jù)接口。
-
即使當(dāng)Java 1.5在語言級(jí)別提供了對(duì)元數(shù)據(jù)的支持時(shí),提供了一個(gè)如此的抽象仍然是有價(jià)值的:
-
JSR-175的元數(shù)據(jù)是靜態(tài)的。它是在編譯時(shí)與某一個(gè)類關(guān)聯(lián),而在部署環(huán)境下是不可改變的。 這里會(huì)需要多層次的元數(shù)據(jù),以支持在部署時(shí)重載某些attribute的值--舉例來說, 在一個(gè)XML文件中定義用于覆蓋的attribute。
-
JSR-175的元數(shù)據(jù)是通過Java反射API返回的。這使得在測(cè)試時(shí)無法模擬元數(shù)據(jù)。 Spring提供了一個(gè)簡(jiǎn)單的接口來允許這種模擬。
-
雖然Spring在Java 1.5達(dá)到它的GA版本之前將支持JSR-175,但仍會(huì)繼續(xù)提供一個(gè)attribute抽象API。
Spring的Attributes接口看起來是這樣的:
public interface Attributes {Collection getAttributes(Class targetClass);Collection getAttributes(Class targetClass, Class filter);Collection getAttributes(Method targetMethod);Collection getAttributes(Method targetMethod, Class filter);Collection getAttributes(Field targetField);Collection getAttributes(Field targetField, Class filter); }這是個(gè)最普通不過的命名者接口。JSR-175能提供更多的功能,比如定義在方法參數(shù)上的attributes。 在1.0版本時(shí),Spring目的在于提供元數(shù)據(jù)的一個(gè)子集,使得能象EJB或.NET一樣提供有效的聲明式企業(yè)級(jí)服務(wù)。 1.0版本以后,Spring將提供更多的元數(shù)據(jù)方法。
注意到該接口像.NET一樣提供了Object類型的attibute。 這使得它區(qū)別于一些僅提供String類的attribute的attribute系統(tǒng), 比如Nanning Aspects和JBoss 4(在DR2版本時(shí))。支持Object類型的attribute有一個(gè)顯著的優(yōu)點(diǎn)。 它使attribute含有類層次,還可以使attribute能夠靈活的根據(jù)它們的配置參數(shù)起作用。
對(duì)于大多數(shù)attribute提供者來說,attribute類的配置是通過構(gòu)造函數(shù)參數(shù)或JavaBean的屬性完成的。Commons Attributes同時(shí)支持這兩種方式。
同所有的Spring抽象API一樣,Attributes是一個(gè)接口。 這使得在單元測(cè)試中模擬attribute的實(shí)現(xiàn)變得容易起來。
8.3.?集成Jakarta Commons Attributes
雖然為其他元數(shù)據(jù)提供者來說,提供org.springframework.metadata.Attributes?接口的實(shí)現(xiàn)很簡(jiǎn)單,但是目前Spring只是直接支持Jakarta Commons Attributes。
Commons Attributes 2.0?(http://jakarta.apache.org/commons/sandbox/attributes/) 是一個(gè)功能很強(qiáng)的attribute解決方案。它支持通過構(gòu)造函數(shù)參數(shù)和JavaBean屬性來配置attribute, 也提供了更好的attribute定義的文檔。(對(duì)JavaBean屬性的支持是在Spring team的要求下添加的。)
我們已經(jīng)看到了兩個(gè)Commons Attributes的attribute定義的例子。通常,我們需要解釋一下:
-
Attribute類的名稱。 這可能是一個(gè)FQN,就像上面的那樣。如果相關(guān)的attribute類已經(jīng)被導(dǎo)入, 就不需要FQN了。你也可以在attibute編譯器的設(shè)置中指定attribute的包名。
-
任何必須的參數(shù)化,可以通過構(gòu)造函數(shù)參數(shù)或者JavaBean屬性完成。
Bean的屬性如下:
/*** @@MyAttribute(myBooleanJavaBeanProperty=true)*/把構(gòu)造函數(shù)參數(shù)和JavaBean屬性結(jié)合在一起也是可以的(就像在Spring IoC中一樣)。
因?yàn)?#xff0c;并不象Java 1.5中的attribute一樣,Common Attributes沒有和Java語言本身結(jié)合起來, 因此需要運(yùn)行一個(gè)特定的attribute編譯的步驟作為整個(gè)構(gòu)建過程的一部分。
為了在整個(gè)構(gòu)建過程中運(yùn)行Commmons Attributes,你需要做以下的事情。
1.復(fù)制一些必要的jar包到$ANT_HOME/lib目錄下。 有四個(gè)必須的jar包,它們包含在Spring的發(fā)行包里:
-
Commons Attributes編譯器的jar包和API的jar包。
-
來自于XDoclet的xjavadoc.jar
-
來自于Jakarta Commons的commons-collections.jar
2.把Commons Attributes的ant任務(wù)導(dǎo)入到你的項(xiàng)目構(gòu)建腳本中去,如下:
<taskdef resource="org/apache/commons/attributes/anttasks.properties"/>3.接下來,定義一個(gè)attribute編譯任務(wù),它將使用Commons Attributes的attribute-compiler任務(wù) 來“編譯”源代碼中的attribute。這個(gè)過程將生成額外的代碼至destdir屬性指定的位置。 在這里我們使用了一個(gè)臨時(shí)目錄:
<target name="compileAttributes" ><attribute-compiler destdir="${commons.attributes.tempdir}" ><fileset dir="${src.dir}" includes="**/*.java"/></attribute-compiler></target>運(yùn)行javac命令編譯源代碼的編譯目標(biāo)任務(wù)應(yīng)該依賴于attribute編譯任務(wù),還需要編譯attribute時(shí)生成至 目標(biāo)臨時(shí)目錄的源代碼。如果在attribute定義中有語法錯(cuò)誤,通常都會(huì)被attribute編譯器捕獲到。 但是,如果attribute定義在語法上似是而非,卻使用了一些非法的類型或類名, 編譯所生成的attribute類可能會(huì)失敗。在這種情況下,你可以看看所生成的類來確定錯(cuò)誤的原因。
Commons Attributes也提供對(duì)Maven的支持。請(qǐng)參考Commons Attributes的文檔得到進(jìn)一步的信息。雖然attribute編譯的過程可能看起來復(fù)雜,實(shí)際上是一次性的耗費(fèi)。一旦被創(chuàng)建后,attribute的編譯是遞增式的, 所以通常它不會(huì)減慢整個(gè)構(gòu)建過程。一旦編譯過程完成后, 你可能會(huì)發(fā)現(xiàn)本章中描述的attribute的使用將節(jié)省在其他方面的時(shí)間。
如果需要attribute的索引支持(目前只在Spring的以attribute為目標(biāo)的web控制器中需要,下面會(huì)討論到), 你需要一個(gè)額外的步驟,執(zhí)行在包含編譯后的類的jar文件上。在這步可選的步驟中, Commons Attributes將生成一個(gè)所有在你源代碼中定義的attribute的索引,以便在運(yùn)行時(shí)進(jìn)行有效的查找。 該步驟如下:
<attribute-indexer jarFile="myCompiledSources.jar"><classpath refid="master-classpath"/></attribute-indexer> 可以到Spring jPetStore例程下的attributes目錄下察看關(guān)于該構(gòu)建過程的例子。 你可以使用它里面的構(gòu)建腳本,并修改該腳本以適應(yīng)你自己的項(xiàng)目。如果你的單元測(cè)試依賴于attribute,盡量使它依賴于Spring對(duì)于Attribute的抽象,而不是Commons Attributes。 這不僅僅為了更好的移植性——舉例來說,你的測(cè)試用例將來仍可以工作如果你轉(zhuǎn)換至Java 1.5的attributes—— 它也簡(jiǎn)化了測(cè)試。Commons Attributes是靜態(tài)的API,而Spring提供的是一個(gè)容易模擬的元數(shù)據(jù)接口。
8.4.?元數(shù)據(jù)和Spring AOP自動(dòng)代理
元數(shù)據(jù)attributes最重要的用處是和Spring AOP的聯(lián)合。 提供類似于.NET風(fēng)格的編程模式,聲明式的服務(wù)會(huì)被自動(dòng)提供給聲明了元數(shù)據(jù)attribute的應(yīng)用對(duì)象。 這樣的元數(shù)據(jù)attribute可以像在聲明式事務(wù)管理一樣被框架直接支持,也可以是自定義的.
這就是AOP和元數(shù)據(jù)attribute配合使用的優(yōu)勢(shì)所在。
8.4.1.?基礎(chǔ)
基于Spring AOP自動(dòng)代理功能實(shí)現(xiàn)。配置可能象這樣:
<bean id="autoproxy" class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"> </bean><bean id="transactionAttributeSource"class="org.springframework.transaction.interceptor.AttributesTransactionAttributeSource"autowire="constructor"> </bean><bean id="transactionInterceptor"class="org.springframework.transaction.interceptor.TransactionInterceptor"autowire="byType"> </bean><bean id="transactionAdvisor"class="org.springframework.transaction.interceptor.TransactionAttributeSourceAdvisor"autowire="constructor" > </bean><bean id="attributes"class="org.springframework.metadata.commons.CommonsAttributes" />這里的基本概念和AOP章節(jié)中關(guān)于自動(dòng)代理的討論一致。
最重要的bean的定義名稱為autoproxy和?transactionAdvisor。要注意bean的實(shí)際名稱并不重要; 關(guān)鍵是它們的類。
所定義的自動(dòng)代理bean?org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator?將自動(dòng)通知(“自動(dòng)代理”)當(dāng)前工廠類中的所有符合Advisor實(shí)現(xiàn)的bean實(shí)例, 這個(gè)類并不知道attribute,而是依賴符合的Advisors的切入點(diǎn)。這些切入點(diǎn)知道attribute的內(nèi)容。
因而我們只是需要一個(gè)AOP的advisor來提供基于attribute的聲明式事務(wù)管理。
也可以添加任意的自定義Advisor實(shí)現(xiàn),它們將被自動(dòng)計(jì)算并應(yīng)用。 (如果有必要的話,你可以使用切入點(diǎn)除了符合自動(dòng)代理配置的attribute,而且滿足一定規(guī)則的Advisor。)
最后,attributes?bean使用的是Commons Attributes的實(shí)現(xiàn)。 也可以用org.springframework.metadata.Attributes的另一個(gè)實(shí)現(xiàn)代替。
8.4.2.?聲明式事務(wù)管理
源代碼級(jí)的attribute的最普通用法是提供了類似.NET的聲明式事務(wù)管理。一旦定義好上面的bean定義, 你就能定義任意數(shù)目的需要聲明式事務(wù)的應(yīng)用對(duì)象了。只有那些擁有事務(wù)attribute的類或方法會(huì)被有事務(wù)的通知。 除了定義你需要的事務(wù)attribute以外,其他什么都不用做。
不象在.NET中那樣,你可以在類或方法級(jí)別指定事務(wù)attribute。 如果指定了類級(jí)別的attribute,它的所有方法都會(huì)“繼承”它。 方法中定義的attribute將完全覆蓋類上定義的attribute。
8.4.3.?緩沖池技術(shù)
再者,象.NET中一樣,你可以通過在類上指定attribute增加緩沖池行為。 Spring能把該行為應(yīng)用到任何普通Java對(duì)象上。你只需在需要緩沖的業(yè)務(wù)對(duì)象上指定一個(gè)緩沖池的attribute,如下:
/** * @@org.springframework.aop.framework.autoproxy.target.PoolingAttribute (10)* * @author Rod Johnson*/ public class MyClass {你需要通常的自動(dòng)代理的基本配置。 然后指定一個(gè)支持緩沖池的TargetSourceCreator,如下所示。 由于緩沖池會(huì)影響目標(biāo)對(duì)象的創(chuàng)建,我們不能使用一個(gè)通常的advice。 注意如果一個(gè)類有緩沖池的attribute,即使沒有任何advisors應(yīng)用到該類,緩沖池也會(huì)對(duì)該類起作用。
<bean id="poolingTargetSourceCreator"class="org.springframework.aop.framework.autoproxy.metadata.AttributesPoolingTargetSourceCreator"autowire="constructor" > </bean>對(duì)應(yīng)的自動(dòng)代理bean定義需要指定一系列的“自定義的目標(biāo)源生成器”,包括支持緩沖池的目標(biāo)源生成者。 我們可以修改上面的例子來引入這個(gè)屬性,如下:
<bean id="autoproxy" class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"> ><property name="customTargetSourceCreators"><list><ref local="poolingTargetSourceCreator" /></list></property> </bean>就像通常在Spring中使用元數(shù)據(jù)一樣,這是一次性的耗費(fèi):一旦創(chuàng)建完成后, 在其它業(yè)務(wù)對(duì)象上使用緩沖池是非常容易的。
對(duì)于很少需要緩沖池技術(shù)的地方,很少需要緩沖大量業(yè)務(wù)對(duì)象,這是就值得斟酌了。 因此這個(gè)功能好像也不是經(jīng)常使用。詳細(xì)請(qǐng)參考o(jì)rg.springframework.aop.framework.autoproxy包的Javadoc。 除了以最少的代碼量使用Commons Pool以外,其它的緩沖池實(shí)現(xiàn)也是可以的。
8.4.4.?自定義的元數(shù)據(jù)
由于自動(dòng)代理底層架構(gòu)的靈活性,我們甚至還可以超越.NET元數(shù)據(jù)attribute的功能。
我們可以定義一些自定義的attribute來提供任何種類的行為。為了達(dá)到這個(gè)目的,你需要:
-
定義你的自定義attribute類
-
定義一個(gè)Spring AOP Advisor,自定義attributes的出現(xiàn)的時(shí)候觸發(fā)它的切入點(diǎn)。
-
把Advisor當(dāng)作一個(gè)bean的定義添加到一個(gè)包含普通自動(dòng)代理基礎(chǔ)架構(gòu)的應(yīng)用上下文中。
-
把a(bǔ)ttribute添加到普通Java對(duì)象上。
有幾個(gè)潛在的領(lǐng)域中你可能想這么做,比如自定義的聲明式安全管理,或者可能的緩存。
這是一個(gè)功能很強(qiáng)的機(jī)制,它能顯著減少某些工程中的配置工作。但是,要記住它在底層是依賴AOP的。 你在應(yīng)用的使用的Advisors越多,運(yùn)行時(shí)配置將會(huì)越復(fù)雜。(如果你想查看object上應(yīng)用了哪些通知, 可以看一下關(guān)于org.springframework.aop.framework.Advised的參考。它使你能夠檢查相關(guān)的Advisors。)8.5.?使用attribute盡可能減少M(fèi)VC web層配置
Spring 1.0中的元數(shù)據(jù)的另一個(gè)主要用法是為簡(jiǎn)化Spring MVC web配置提供了一個(gè)選擇。
Spring MVC提供了靈活的處理器映射: 將外來的請(qǐng)求映射到控制器(或其它的處理器)實(shí)例上。 通常上處理器映射被配置在相應(yīng)的Spring DispatcherServlet的xxx-servlet.xml文件中。
把這些配置定義在DispatcherServlet的配置文件中通常是個(gè)不錯(cuò)的選擇。它提供了最大的靈活性。 特別的是:
-
Controller實(shí)例是顯式的被Spring IoC通過XML bean定義來管理。
-
該映射位于controller的外面, 所以相同controller的實(shí)例可以在同一個(gè)DispatcherServlet中被賦予不同的映射或者在不同的配置中重用。
-
Spring MVC能夠支持在任何規(guī)則上的映射,而不是大多數(shù)其它框架中僅有的將請(qǐng)求URL映射到控制器。
然而,對(duì)于每個(gè)controller來說,我們同時(shí)需要一個(gè)處理器映射(通常是一個(gè)處理器映射的XML bean定義), 和一個(gè)控制器自身的一個(gè)XML映射描述。
Spring提供了一個(gè)基于源代碼級(jí)attribute的更簡(jiǎn)單的方法,對(duì)于一些簡(jiǎn)單場(chǎng)景來說是一個(gè)吸引人的選擇。
這一段描述的方法很適合一些簡(jiǎn)單的MVC場(chǎng)景。但它犧牲了一些Spring MVC的功能, 比如根據(jù)不同的映射使用相同的控制器,把映射基于除了請(qǐng)求的URL之外的規(guī)則。在這種方法下,控制器上標(biāo)記了一個(gè)或多個(gè)類級(jí)的元數(shù)據(jù)attribute, 每一個(gè)attribute指定了它們應(yīng)該映射的一個(gè)URL。
下面的例子展示了這種方法。在每一種情況下,我們都有一個(gè)依賴于Cruncher類的業(yè)務(wù)對(duì)象控制器。 和往常一樣,這種依賴性將通過依賴注射來解決。 Cruncher必須作為一個(gè)bean定義出現(xiàn)在相關(guān)的DispatcherServlet的XML文件中,或在一個(gè)父上下文中。
我們把一個(gè)attribute設(shè)置到控制器類上,并指定應(yīng)該映射的URL。 我們可以通過JavaBean屬性或構(gòu)造函數(shù)參數(shù)來表達(dá)依賴關(guān)系。這種映射必須通過自動(dòng)裝配來解決: 那就是說,在上下文中必須只能有一個(gè)Crucher類型的業(yè)務(wù)對(duì)象。
/*** Normal comments here* @author Rod Johnson* @@org.springframework.web.servlet.handler.metadata.PathMap("/bar.cgi")*/ public class BarController extends AbstractController {private Cruncher cruncher;public void setCruncher(Cruncher cruncher) {this.cruncher = cruncher;}protected ModelAndView handleRequestInternal(HttpServletRequest arg0, HttpServletResponse arg1) throws Exception {System.out.println("Bar Crunching c and d =" + cruncher.concatenate("c", "d"));return new ModelAndView("test");}}為了使這個(gè)自動(dòng)映射起作用,我們需要添加下面的配置到相關(guān)的xxxx-servlet.xml文件中, 這些配置是用來指定相關(guān)attribute的處理器映射的。 這個(gè)特殊的處理器映射可以處理任意數(shù)量的象上面一樣帶有attribute的控制器。 Bean的id(“commonsAttributesHandlerMapping”)并不重要。關(guān)鍵是它的類型:
<bean id="commonsAttributesHandlerMapping" class="org.springframework.web.servlet.handler.metadata.CommonsPathMapHandlerMapping" />現(xiàn)在我們并不需要一個(gè)象上面例子中的Attributes bean的定義, 因?yàn)檫@個(gè)類直接利用Commons Attributes API,而不是通過Spring的元數(shù)據(jù)抽象。
現(xiàn)在我們不再需要對(duì)每一個(gè)控制器提供XML配置。控制器被自動(dòng)映射到指定的URL上。 控制器得益于IoC,使用了Spring的自動(dòng)裝配功能。舉例來說, 上述的簡(jiǎn)單控制器中的“cruncher”屬性上的依賴性會(huì)自動(dòng)在當(dāng)前的web應(yīng)用中解決. Setter方法和構(gòu)造函數(shù)依賴注射都是可以的,每一個(gè)都是零配置。
構(gòu)造函數(shù)注冊(cè)的一個(gè)例子,同時(shí)演示了多個(gè)URL路徑:
/** * Normal comments here * @author Rod Johnson * * @@org.springframework.web.servlet.handler.metadata.PathMap("/foo.cgi") * @@org.springframework.web.servlet.handler.metadata.PathMap("/baz.cgi") */ public class FooController extends AbstractController {private Cruncher cruncher;public FooController(Cruncher cruncher) {this.cruncher = cruncher;}protected ModelAndView handleRequestInternal(HttpServletRequest arg0, HttpServletResponse arg1) throws Exception {return new ModelAndView("test");}}這種方法有著下列的好處:
-
顯著的減少配置工作量。每一次我們?cè)黾右粋€(gè)控制器時(shí),我們不需要XML的配置。 就像attribute驅(qū)動(dòng)的事務(wù)管理一樣,一旦有了基礎(chǔ)架構(gòu)后,添加更多的應(yīng)用類將會(huì)很簡(jiǎn)單。
-
我們保留了Spring IoC配置控制器的能力。
不過該方法有如下的限制:
-
這個(gè)方法使構(gòu)建過程更加復(fù)雜,不過開銷是一次性的。 我們需要一個(gè)attribute編譯步驟和一個(gè)建立attribute的索引步驟。 但是,一旦這些步驟就位后,這將不再是一個(gè)問題。
-
雖然將來會(huì)增加對(duì)其他attribute提供者的支持,但目前只支持Commons Attributes。
-
只有“根據(jù)類型的自動(dòng)裝配”的依賴注射才支持這樣的控制器。但是, 這妨礙這些控制器對(duì)Structs Actions(在框架中并沒有IoC的支持), 和值得斟酌的WebWork Actions(只有基本的IoC支持,并且IoC逐步受到關(guān)注)的領(lǐng)先。
-
依賴自動(dòng)魔法的IoC解決方案可能是令人困惑的。
由于根據(jù)類型的自動(dòng)裝配意味著必須依賴一種指定類型,如果我們使用AOP就需要小心了。 在通常使用TransactionProxyFactoryBean的情況下,舉例來說, 我們對(duì)一個(gè)業(yè)務(wù)接口例如Cruncher有兩個(gè)實(shí)現(xiàn): 一個(gè)為原始的普通Java對(duì)象的定義,另一個(gè)是帶有事務(wù)的AOP代理。這將無法工作, 因?yàn)樗姓邞?yīng)用上下文無法確切的解析這種類型依賴。解決方法是使用AOP的自動(dòng)代理, 建立起自動(dòng)代理的基本架構(gòu),這樣就只有一個(gè)Crucher的實(shí)現(xiàn), 同時(shí)該實(shí)現(xiàn)是自動(dòng)被通知的。 因此這種方法和上面的以attribute為目標(biāo)聲明式服務(wù)能很好的一起工作。 因?yàn)閍ttribute編譯過程必須恰當(dāng)處理web控制器的定位,所有這就很容易被創(chuàng)建
不象其它的元數(shù)據(jù)的功能,當(dāng)前只有Commons Attributes的一種實(shí)現(xiàn): org.springframework.web.servlet.handler.metadata.CommonsPathMapHandlerMapping。 這個(gè)限制是因?yàn)槲覀儾粌H需要attribute編譯,還需要attribute索引: 根據(jù)attribute API來查詢所有擁有PathMap attribute的類。雖然將來可能會(huì)提供, 但目前在org.springframework.metadata.Attributes的抽象接口上還沒有提供索引。 (如果你需要增加另一個(gè)attribute實(shí)現(xiàn)的支持,并且必須支持索引, 你可以簡(jiǎn)單的繼承AbstractPathMapHandlerMapping,CommonsPathMapHandlerMapping的父類, 用你選擇的attribute API來實(shí)現(xiàn)其中兩個(gè)protected的虛方法。)
因此我們?cè)跇?gòu)建過程中需要兩個(gè)額外的步驟:attribute編譯和建立attribute索引。 上面已經(jīng)展示了attributer索引建立器的使用方法。要注意到目前Commons Attributes仍需要一個(gè)Jar文件來建立索引。
如果你開始使用控制器元數(shù)據(jù)映射方法,你可以在任何一個(gè)地方轉(zhuǎn)換至經(jīng)典的Spring XML映射方法。 所以你不需要拒絕這種選擇。正因?yàn)檫@個(gè)原因,我發(fā)現(xiàn)我經(jīng)常在開始一個(gè)web應(yīng)用時(shí)使用元數(shù)據(jù)映射.8.6.?元數(shù)據(jù)attribute的其它使用
對(duì)元數(shù)據(jù)attribute的其它應(yīng)用看來正在流行。到2004年3月時(shí), 一個(gè)為Spring建立的基于attribute的驗(yàn)證包正在開發(fā)中。 當(dāng)考慮到潛在的多次使用時(shí),attribute解析的一次性開銷看起來更加吸引人了.
8.7.?增加對(duì)其它的元數(shù)據(jù)API的支持
如果你希望提供對(duì)另一種元數(shù)據(jù)API的支持,這是容易做到的。
簡(jiǎn)單的實(shí)現(xiàn)org.springframework.metadata.Attributes?接口作為你選擇的元數(shù)據(jù)API的 外觀(facade)。然后你就可以象上面那樣把這個(gè)對(duì)象包括到你的bean定義中去。
所有使用元數(shù)據(jù)的框架服務(wù),例如AOP元數(shù)據(jù)驅(qū)動(dòng)的自動(dòng)代理,將自動(dòng)使用你的新元數(shù)據(jù)提供者。
我們期待著增加對(duì)Java 1.5的attribute的支持--可能作為Spring核心的附件--在2004年第二季度。from:?http://docs.huihoo.com/spring/zh-cn/metadata.html
總結(jié)
以上是生活随笔為你收集整理的Spring - Java/J2EE Application Framework 应用框架 第 8 章 源代码级的元数据支持的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Spring - Java/J2EE A
- 下一篇: Spring - Java/J2EE A