時(shí)間:2005-10-24 作者:Alexandre Vasseur,?Aspect Werkz,?Joakim Dahlstedt,?Jonas Bonér |
前一篇文章 介紹了面向方面編程和關(guān)注點(diǎn)分離的概念,解釋了這種概念如何在方面構(gòu)造的幫助下增強(qiáng)軟件的模塊化,以及如何使用它來補(bǔ)充面向?qū)ο缶幊獭7矫娲砟K化的單元,并且由切點(diǎn)(何處)、建議(什么)以及類型間聲明(在這個(gè)新的方面補(bǔ)充對(duì)象模型)組成。有許多技術(shù)可以將關(guān)注點(diǎn)編織進(jìn)應(yīng)用程序,在當(dāng)今的Java領(lǐng)域中,最常用的技術(shù)是字節(jié)碼測(cè)試,在AspectWerkz和AspectJ(從1.1版開始)中實(shí)現(xiàn)了這種技術(shù)。
但是,這種AOP實(shí)現(xiàn)方式具有幾個(gè)缺點(diǎn),本系列的第1篇文章對(duì)此進(jìn)行了詳細(xì)解釋。盡管在字節(jié)碼測(cè)試領(lǐng)域還有很大的發(fā)展余地(包括Java 5中的JVMTI/JSR-163測(cè)試代理規(guī)范和高效字節(jié)碼操作庫,比如ObjectWeb ASM),但字節(jié)碼測(cè)試代價(jià)不菲。此外,已經(jīng)證明,使用字節(jié)碼測(cè)試實(shí)現(xiàn)AOP是不完善的。例如,如果不采用非常特殊且效率低下的解決方案,就無法通過切點(diǎn)匹配反射式方法調(diào)用或get和set字段。總的來說,所有基于字節(jié)碼測(cè)試的產(chǎn)品都受到字節(jié)碼測(cè)試技術(shù)相關(guān)問題的影響,而且隨著這種技術(shù)的普及,問題將逐漸增加。
所有這些缺點(diǎn)促使JRockit團(tuán)隊(duì)提出了JVM對(duì)AOP的支持。其目標(biāo)是盡可能全面地實(shí)現(xiàn)當(dāng)前的AOP語義,同時(shí)不把JVM限制在某個(gè)特定的面向方面框架的語言細(xì)節(jié)和編程模型上。
本文通過具體的代碼示例介紹該API,然后描述其好處及未來的發(fā)展方向。
我們的動(dòng)機(jī)讓我們快速地回顧引入JVM的AOP支持的技術(shù)動(dòng)機(jī)。
JVM編織是對(duì)上面提到的問題最自然的解決方案。為了說明其原因,我們將引入兩個(gè)例子,它們說明JVM已經(jīng)完成了編織所涉及的大多數(shù)工作:當(dāng)加載一個(gè)類時(shí),JVM讀取字節(jié)碼,建立為java.lang.reflect.* API進(jìn)行服務(wù)所需的數(shù)據(jù);另一個(gè)例子是方法調(diào)度。目前的JVM將方法或代碼塊的字節(jié)碼編譯為更高級(jí)、效率也更高的構(gòu)造和執(zhí)行流(在適用代碼內(nèi)聯(lián)的地方進(jìn)行代碼內(nèi)聯(lián))。由于HotSwap API的需要,JRockit JVM(可能還包括其他JVM)還會(huì)記錄哪個(gè)方法調(diào)用了其他方法,因此如果在運(yùn)行時(shí)重新定義某個(gè)類,那么在所有期望的位置(內(nèi)聯(lián)的或非內(nèi)聯(lián)的),類中定義的方法主體仍然可以進(jìn)行熱交換。
因此,不必為了編織進(jìn)一個(gè)建議調(diào)用而修改字節(jié)碼,比如說,在特定的方法調(diào)用之前。JVM實(shí)際上可以掌握關(guān)于這個(gè)建議調(diào)用的知識(shí),它會(huì)在任何匹配的聯(lián)結(jié)點(diǎn)上對(duì)此建議進(jìn)行調(diào)度,然后再調(diào)度實(shí)際的方法。
由于不接觸字節(jié)碼,立即可以獲得以下好處:
- 不會(huì)由于字節(jié)碼測(cè)試而產(chǎn)生啟動(dòng)開銷。
- 對(duì)于在任何位置、任何時(shí)間、以遞增式開銷添加和刪除建議的完全的運(yùn)行時(shí)支持。
- 對(duì)建議的反射式調(diào)用的隱式支持。
- 不需要將類模型復(fù)制到特定于框架的某些結(jié)構(gòu),因此減少了額外的內(nèi)存占用。
與JVMDI_EVENT_METHOD_ENTRY或JVMDI_EVENT_FIELD_ACCESS等JVMDI規(guī)范中定義的眾所周知的C級(jí)別事件相比,這種方式有很大區(qū)別。在JVMDI中,必須首先處理C級(jí)別API,這使得它對(duì)于大多數(shù)開發(fā)人員來說有些復(fù)雜,而且難以分發(fā)。其次,規(guī)范沒有提供細(xì)粒度的聯(lián)結(jié)點(diǎn)匹配機(jī)制,而是要求預(yù)定所有這樣的事件。這仍然會(huì)導(dǎo)致顯著的開銷,因此不得不進(jìn)行調(diào)試。
我們的方法我們想讓您先了解一下如何在JVM中添加AOP支持。關(guān)鍵之處在于我們?cè)贘ava API級(jí)別上提供了動(dòng)作調(diào)度和預(yù)定(下面會(huì)詳細(xì)描述)。因此,您可以寫出下面這樣的代碼:
Weaver w = WeaverFactory.getWeaver();Method staticActionMethod =SimpleAction.class.getDeclaredMethod
("simpleStaticAction",new Class[0]//no arguments);
MethodSubscription ms = new MethodSubscription
(/* where to match*/,InsertionType.BEFORE,staticActionMethod);
w.addSubscription(ms);
如您所見,我們提供了一個(gè)可訪問的JVM API,可以用它來實(shí)現(xiàn)更傳統(tǒng)的AOP方法。這為解決前面提到的傳統(tǒng)AOP實(shí)現(xiàn)問題提供了極大的靈活性,而且也使其他使用方式成為可能。下面幾節(jié)將詳細(xì)介紹這個(gè)API。
動(dòng)作調(diào)度和預(yù)定JRockit JVM AOP支持公開了一個(gè)Java API,它與JVM方法調(diào)度和對(duì)象模型組件緊密集成在一起。為了確保不使JVM被限制在當(dāng)前或未來的任何特定于AOP的技術(shù)方向上,我們決定實(shí)現(xiàn)一個(gè)動(dòng)作調(diào)度和預(yù)定模型。
這個(gè)API使您能夠在指定的切點(diǎn)上描述定義良好的預(yù)定,這樣就能夠注冊(cè)JVM將要調(diào)度的動(dòng)作。動(dòng)作由以下組件組成:
- 一個(gè)常規(guī)Java方法——我們稱之為動(dòng)作方法,對(duì)于每個(gè)匹配這個(gè)預(yù)定的聯(lián)結(jié)點(diǎn),都將調(diào)用這個(gè)方法。
- 一個(gè)可選的動(dòng)作實(shí)例,在這個(gè)實(shí)例上調(diào)用動(dòng)作方法。
- 一組可選的參數(shù)級(jí)注釋,它們向JVM指出動(dòng)作方法期望從調(diào)用堆棧獲得哪些參數(shù)。
動(dòng)作還可以分為before動(dòng)作、after returning動(dòng)作、after throwing動(dòng)作或者instead-of動(dòng)作(類似于AOP的“around”概念)。
為了調(diào)用這個(gè)API,必須獲得一個(gè)jrockit.ext.weaving.Weaver實(shí)例的句柄。這個(gè)編織器實(shí)例根據(jù)它的調(diào)用者上下文來控制允許進(jìn)行哪些操作。例如,在容器級(jí)編織器可以預(yù)定特定于應(yīng)用程序的聯(lián)結(jié)點(diǎn)時(shí),用戶可能不希望部署在應(yīng)用服務(wù)器中的應(yīng)用程序創(chuàng)建編織器,從而預(yù)定某些容器級(jí)或特定于JDK的聯(lián)結(jié)點(diǎn)的動(dòng)作方法。這種編織器可見性理念反映了底層類加載器的委托模型。
我們簡(jiǎn)單介紹一下這些構(gòu)造如何映射到常規(guī)的AOP構(gòu)造,這有助于理解這個(gè)模型:
·預(yù)定可以視為一個(gè)有類型的聯(lián)結(jié)點(diǎn),或者就是一個(gè)有類型的聯(lián)結(jié)點(diǎn)(字段get()、set()、方法call()等等),加上一個(gè)within()/withincode()切點(diǎn)。
·動(dòng)作實(shí)例可以視為方面實(shí)例。
·動(dòng)作方法可以視為建議。
熟悉AOP的讀者可能已經(jīng)看出,要想用這個(gè)JVM級(jí)API實(shí)現(xiàn)一個(gè)完整的AOP框架,還需要進(jìn)行一些開發(fā),包括一個(gè)(按照規(guī)定)管理方面實(shí)例化模型的中間層、cflow()切點(diǎn)的實(shí)現(xiàn)以及切點(diǎn)的完全合成和正交的實(shí)現(xiàn)。
API細(xì)節(jié):動(dòng)作方法動(dòng)作方法(與AOP的建議概念相似)就像(作為方面的)常規(guī)類的常規(guī)Java方法。它可以是static方法,也可以是成員方法。它的返回類型必須符合某些隱式約定,而且before動(dòng)作的返回類型應(yīng)該是void。對(duì)于instead-of動(dòng)作(類似于AOP的around建議語義),其返回類型還是作為動(dòng)作調(diào)用結(jié)果的堆棧的類型。
動(dòng)作方法可以有參數(shù),參數(shù)的注釋進(jìn)一步控制上下文公開,如下面的代碼示例所示:
import java.lang.reflect.*;import jrockit.ext.weaving.*;?
public class SimpleAction
{? public static void simpleStaticAction()
{out.println("hello static action!");
}
?public void simpleAction() {out.println("hello action!");
}
?public void simpleAction(@CalleeMethod WMethod calleeM,@CallerMethod WMethod callerM)
{out.println(callerM.getMethod().getName());
out.println(" calling ");
out.println(calleeM.getMethod().getName());
}?
}
該代碼示例引入了jrockit.ext.weaving.WMethod類。該類用作java.lang.reflect.Method、java.lang.reflect.Constructor和類的靜態(tài)初始化器(它在java.lang.reflect.*中沒有出現(xiàn))的包裝器。這與AspectJ JoinPoint.StaticPart.getSignature()抽象化相似。
下面是當(dāng)前定義的注釋及其含義。
注釋 | 公開 | 備注 |
@CalleeMethod | 被調(diào)用者方法(方法、構(gòu)造函數(shù)、靜態(tài)初始化器) | ? |
@CallerMethod | 調(diào)用者方法(方法、構(gòu)造函數(shù)、靜態(tài)初始化器) | ? |
@Callee | 被調(diào)用者實(shí)例 | 濾除靜態(tài)成員調(diào)用。用作instance-of型過濾器:被調(diào)用者類型必須是所注釋的參數(shù)類型的實(shí)例。 |
@Caller | 調(diào)用者實(shí)例 | 濾除來自靜態(tài)成員的調(diào)用。用作instance-of型過濾器:調(diào)用者類型必須是所注釋的參數(shù)類型的實(shí)例。 |
@Arguments | 調(diào)用參數(shù) | ? |
為了支持instead-of,并能夠決定是否沿著截取鏈前進(jìn)(就像在AOP中通過JoinPoint.proceed()概念實(shí)現(xiàn)),我們引入了jrockit.ext.weaving.InvocationContext構(gòu)造,如下所示:
import jrockit.ext.weaving.*; public class InsteadOfAction { public Object instead( InvocationContext jp, @CalleeMethod Method callee) { return jp.proceed(); } }
API的細(xì)節(jié):動(dòng)作實(shí)例和動(dòng)作類型
正如前面代碼示例中所示,動(dòng)作方法可以是靜態(tài)的,也可以不是。如果動(dòng)作方法不是靜態(tài)的,那么就必須傳遞一個(gè)動(dòng)作實(shí)例,JVM在這個(gè)實(shí)例上調(diào)用動(dòng)作方法。
其語法風(fēng)格與Java開發(fā)人員使用java.lang.reflect.Method.invoke(null/*static method*/, .../*args*/)對(duì)方法進(jìn)行反射式調(diào)用一樣。但是,利用JVM的AOP支持,底層的動(dòng)作調(diào)用根本不涉及任何反射。
允許用戶控制動(dòng)作實(shí)例,就會(huì)產(chǎn)生有趣的用例。例如,可以實(shí)現(xiàn)一個(gè)簡(jiǎn)單的委托模式,在運(yùn)行時(shí)用另一個(gè)實(shí)現(xiàn)替換整個(gè)動(dòng)作實(shí)例,而不涉及JVM的內(nèi)部組件。
注意,這將有助于(按照規(guī)定)實(shí)現(xiàn)AOP方面實(shí)例化模型,比如issingleton()、pertarget()、perthis()、percflow()等等,同時(shí)不會(huì)將JVM API限制在某些預(yù)定義的語義上。
在將預(yù)定注冊(cè)到編織器實(shí)例之前,賦予它一個(gè)類型作為建議類型:before、instead-of、after-returning或after-throwing。
可以編寫下面這樣的代碼來創(chuàng)建預(yù)定:
// Get a Weaver instance that will act as a // container for the subscription(s) we create Weaver w = WeaverFactory.getWeaver(); // regular java.lang.reflect is used to refer // to the action method "simpleStaticAction()" Method staticActionMethod = SimpleAction.class.getDeclaredMethod( "simpleStaticAction", new Class[0]//no arguments ); MethodSubscription ms = new MethodSubscription( .../* where to match*/, InsertionType.BEFORE, staticActionMethod ); w.addSubscription(ms);
該代碼示例假設(shè)用戶使用靜態(tài)動(dòng)作方法實(shí)現(xiàn)。也可以使用實(shí)例方法編寫這個(gè)示例,在這種情況下,應(yīng)該傳遞給MethodSubscription一個(gè)包含類實(shí)例。
// Use of an action instance to refer to the // non static action method "simpleAction()" Method actionMethod = SimpleAction.class.getDeclaredMethod( "simpleAction", new Class[0]// no arguments ); // Instantiate the action instance SimpleAction actionInstance = new SimpleAction(); MethodSubscription ms2 = new MethodSubscription( ...,// where to match, explained below InsertionType.BEFORE, actionMethod, actionInstance ); w.addSubscription(ms2);
諸如within()和withincode()類型模式之類的AOP語義也通過該API的變體實(shí)現(xiàn)。
API細(xì)節(jié):預(yù)定
如前面的代碼示例所示,預(yù)定API依賴于java.lang.reflect.*對(duì)象模型和一些簡(jiǎn)單的抽象化(比如jrockit.ext.weaving.WMethod)來合并方法、構(gòu)造函數(shù)和類的靜態(tài)初始化器處理。
new MethodSubscription(...)調(diào)用的第一個(gè)參數(shù)必須是jrockit.ext.weaving.Filter實(shí)例,這個(gè)實(shí)例具有幾個(gè)具體實(shí)現(xiàn)以便匹配方法、字段等等。
jrockit.ext.weaving.MethodFilter實(shí)例用作定義,JVM編織器實(shí)現(xiàn)根據(jù)它進(jìn)行聯(lián)結(jié)點(diǎn)陰影匹配(shadow matching)。jrockit.ext.weaving.MethodFilter允許根據(jù)以下各項(xiàng)進(jìn)行過濾(還提供額外的結(jié)構(gòu)支持within()/withincode()語義):
- 方法修飾符(比如使用java.lang.reflect.Modifier時(shí)的int)。
- Class<? extends java.lang.annotation.Annotation>,匹配方法運(yùn)行時(shí)可見性注釋。
- jrockit.ext.weaving.ClassFilter實(shí)例,匹配聲明類型。
- jrockit.ext.weaving.StringFilter實(shí)例,匹配方法名。
- jrockit.ext.weaving.ClassFilter實(shí)例,匹配方法返回類型。
- jrockit.ext.weaving.UserDefinedFilter實(shí)例,用于實(shí)現(xiàn)更精細(xì)的匹配邏輯。
使用jrockit.ext.weaving.UserDefinedFilter回調(diào)機(jī)制來實(shí)現(xiàn)更高級(jí)的匹配方式(與Spring AOPorg.springframework.aop.MethodMatcher和org.springframework.aop.ClassFilter相似)。
所有這些結(jié)構(gòu)都是可選的,如果遇到null,就表示“任意匹配”。
jrockit.ext.weaving.ClassFilter提供一種類似的方式:
- Class<? extends java.lang.annotation.Annotation>,匹配類運(yùn)行時(shí)可見性注釋。
- Class,匹配類類型。
- boolean值,表示是否匹配子類型。
因此,以下代碼匹配所有名稱以“bar”開頭的方法調(diào)用。注意,在這個(gè)非常簡(jiǎn)單的例子中傳遞了好幾個(gè)null值:
StringFilter sf = new StringFilter("bar", STARTSWITH); MethodFilter mf = new MethodFilter(0, null, null, sf, null, null); MethodSubscription ms = new MethodSubscription( mf, InsertionType.BEFORE, staticActionMethod ); w.addSubscription(ms);
作為更現(xiàn)實(shí)的例子,以下代碼匹配所有三個(gè)EJB業(yè)務(wù)方法:
// Prepare the pointcut to match // @Stateless annotated classes business methods MethodFilter ejbBizMethods = new MethodFilter( PUBLIC_NONSTATIC, // Method annotation does not matter null, new ClassFilter( // Declaring class, the java.lang.Class // for the EJB we are currently manipulating ejbClass, // no subtypes matching false, // class annotation Stateless.class ), // EJB methods matching is handled // in a UserDefinedFilter below instead null, // return type does not matter null, // custom Filter callback new UserDefinedFilter() { public boolean match( MethodFilter methodFilter, WMember member, WMethod within) { return !isEjbLifeCycleMethod(member); } } );
好處
使用JVM編織而不是字節(jié)碼測(cè)試有幾個(gè)好處。從較高的層面來看,編織作為JVM功能的自然擴(kuò)展出現(xiàn),因此在許多方面它不那么具有侵入性,并且為性能、可伸縮性和可用性各方面帶來了許多好處。
關(guān)于字節(jié)碼編織的問題(尤其是在加載時(shí)編織的情況下)的詳細(xì)討論,請(qǐng)參考本系列的第1部分。以下好處解決了所有這些問題。
- 不使用字節(jié)碼測(cè)試,增強(qiáng)了可伸縮性
字節(jié)碼沒有被修改。在JVM內(nèi)部組件中,仍然采用從字節(jié)碼到可執(zhí)行代碼的常規(guī)編譯管道。使用字節(jié)碼測(cè)試時(shí),需要分析字節(jié)碼指令并用某些中間結(jié)構(gòu)來表示它們,這樣才能在測(cè)試框架(AOP編織器或基于字節(jié)碼測(cè)試的產(chǎn)品)中操縱它們;而使用JVM編織不需要這么做。
編織器變得無所不在了。即使用戶希望在啟動(dòng)時(shí)注冊(cè)預(yù)定,這也不再是必須的。因?yàn)楦静恍枰治鲎止?jié)碼指令來尋找要截取的聯(lián)結(jié)點(diǎn),所以大大減少了應(yīng)用程序的啟動(dòng)時(shí)間。這也提供了開發(fā)真正動(dòng)態(tài)的系統(tǒng)的機(jī)會(huì)——?jiǎng)討B(tài)意味著可以在任何時(shí)候部署方面和解除方面部署,而又不會(huì)由此引起額外的開銷或復(fù)雜性。
- 不使用冗余的類型信息記錄,降低了內(nèi)存耗用并且提高了可伸縮性
因?yàn)椴辉龠M(jìn)行字節(jié)碼測(cè)試,因此與對(duì)象模型雙重記錄問題相關(guān)的問題就不會(huì)出現(xiàn)了。預(yù)定API依賴于java.lang.reflect.*模型,而這個(gè)模型已經(jīng)以類似的方式向Java開發(fā)人員提供了此信息。
- 多個(gè)代理可以保持一致
因?yàn)樗幙椀念惖淖止?jié)碼沒有經(jīng)過修改,所以不會(huì)因?yàn)閮蓚€(gè)不同的代理以不兼容的方式修改字節(jié)碼(相互隱藏原始程序的屬性),而造成沖突。預(yù)定的注冊(cè)次序起到了優(yōu)先權(quán)規(guī)則的作用。注意,如果類是可序列化的,那么不會(huì)為了在運(yùn)行時(shí)執(zhí)行所編織的建議而向其添加隱藏結(jié)構(gòu),所以常規(guī)的序列化將得到充分支持。而字節(jié)碼測(cè)試技術(shù)通常需要確定序列化能力是否有所保留(例如,serialVersionUID字段的處理)。
- 支持截取反射式調(diào)用
通過使用JVM級(jí)方法調(diào)度,所有反射式調(diào)用(方法調(diào)用或者get或set字段)都可以被匹配,就像它們是常規(guī)調(diào)用,而且所有注冊(cè)的動(dòng)作都將被觸發(fā)一樣。這不需要任何額外的開銷,也不涉及特定于實(shí)現(xiàn)的細(xì)節(jié)和復(fù)雜性。
未來的發(fā)展方向
盡管JVM編織很有幫助,而且解決了與字節(jié)碼測(cè)試技術(shù)相關(guān)的可伸縮性和可用性問題,但是仍然必須解決一些缺陷才能使其完美地實(shí)現(xiàn)用例,這可能需要采用一些補(bǔ)充方法。
一些基于字節(jié)碼測(cè)試的產(chǎn)品使用了細(xì)粒度更改,當(dāng)前的JVM AOP API還無法實(shí)現(xiàn)這一特性。某些用例處理同步塊,因此不同的鎖定機(jī)制(如:分布式鎖定)可以透明地注入常規(guī)的應(yīng)用程序。這樣的細(xì)粒度動(dòng)作常常要求對(duì)同步塊進(jìn)行有條件執(zhí)行,甚至完全刪除同步塊,并使用某個(gè)專用鎖定API調(diào)用來替換它。可以在JVM中解決這樣的特定需求,但是實(shí)際上不可能找到一個(gè)對(duì)每種用例都有效的高效解決方案。還有必要提醒一下的是,目前領(lǐng)先的AOP框架還不能將同步塊公開為聯(lián)結(jié)點(diǎn)。
在JVM級(jí)別上,無法輕松地實(shí)現(xiàn)AspectJ定義的某些細(xì)粒度語義。例如,AspectJ支持預(yù)初始化、初始化和構(gòu)造函數(shù)執(zhí)行切點(diǎn)。構(gòu)造函數(shù)執(zhí)行切點(diǎn)挑選出源代碼中出現(xiàn)的構(gòu)造函數(shù),初始化切點(diǎn)挑選出獲得已初始化實(shí)例的所有構(gòu)造函數(shù)執(zhí)行,包括this(...)構(gòu)造函數(shù)委托。JVM難以把握這兩者的差異。更具侵入性的代碼內(nèi)聯(lián)策略可能會(huì)出現(xiàn)在哪些地方實(shí)際上也可能取決于編譯器。
隨著字節(jié)碼測(cè)試逐漸流行起來,新的JVM API的引入肯定會(huì)遇到挑戰(zhàn)。如果要開發(fā)一種同時(shí)適應(yīng)兩種JVM(支持新API的JVM,比如JRockit,以及不支持新API的JVM)的產(chǎn)品,那么成本會(huì)相當(dāng)高。這個(gè)領(lǐng)域中的規(guī)范(如:JSR)可能有助于克服這種困難。
結(jié)束語
字節(jié)碼測(cè)試技術(shù)目前已經(jīng)在不同領(lǐng)域的Java平臺(tái)上得到廣泛使用,從面向方面軟件開發(fā)到更特定于應(yīng)用的解決方案(如:應(yīng)用程序監(jiān)控、持久性或分布式計(jì)算)。隨著字節(jié)碼測(cè)試的可用性和透明性的提高,加載時(shí)編織和部署時(shí)測(cè)試將會(huì)流行起來。
遺憾的是,這種技術(shù)沒有為可伸縮性和可用性需求提供適當(dāng)?shù)闹С帧L貏e是隨著這種技術(shù)的應(yīng)用越來越廣泛,以及對(duì)來自不同產(chǎn)品的不同測(cè)試代理的混合使用,這個(gè)問題會(huì)越來越嚴(yán)重。JVM編織和JVM對(duì)AOP的支持(比如在JRockit中所實(shí)現(xiàn)的)是解決這個(gè)問題的自然方法,可以促進(jìn)革新和技術(shù)發(fā)展。JRockit團(tuán)隊(duì)所提出的Java API將JVM方法調(diào)度內(nèi)部組件與用戶定義的動(dòng)作聯(lián)系起來,僅依賴于java.lang.reflect API的預(yù)定優(yōu)雅地填補(bǔ)了以前的鴻溝,并解決了主要的可伸縮性和可用性問題。
這種新的API要想獲得廣泛采用,需要對(duì)它進(jìn)行認(rèn)真的評(píng)估,并將它應(yīng)用于真實(shí)的用例,比如AOP或者大型應(yīng)用程序的運(yùn)行時(shí)自適應(yīng)。