JRockitJVM對AOP的支援,第2部分(轉)

post0發表於2007-09-07
JRockitJVM對AOP的支援,第2部分(轉)[@more@]

  前一篇文章介紹了面向方面程式設計和關注點分離的概念,解釋了這種概念如何在方面構造的幫助下增強軟體的模組化,以及如何使用它來補充物件導向程式設計。方面代表模組化的單元,並且由切點(何處)、建議(什麼)以及型別間宣告(在這個新的方面補充物件模型)組成。有許多技術可以將關注點編織進應用程式,在當今的Java領域中,最常用的技術是位元組碼測試,在AspectWerkz和AspectJ(從1.1版開始)中實現了這種技術。

  但是,這種AOP實現方式具有幾個缺點,本系列的第1篇文章對此進行了詳細解釋。儘管在位元組碼測試領域還有很大的發展餘地(包括Java 5中的JVMTI/JSR-163測試代理規範和高效位元組碼操作庫,比如ObjectWeb ASM),但位元組碼測試代價不菲。此外,已經證明,使用位元組碼測試實現AOP是不完善的。例如,如果不採用非常特殊且效率低下的解決方案,就無法透過切點匹配反射式方法呼叫或get和set欄位。總的來說,所有基於位元組碼測試的產品都受到位元組碼測試技術相關問題的影響,而且隨著這種技術的普及,問題將逐漸增加。

  所有這些缺點促使JRockit團隊提出了JVM對AOP的支援。其目標是儘可能全面地實現當前的AOP語義,同時不把JVM限制在某個特定的面向方面框架的語言細節和程式設計模型上。

  本文透過具體的程式碼示例介紹該API,然後描述其好處及未來的發展方向。

  我們的動機

  讓我們快速地回顧引入JVM的AOP支援的技術動機。

  JVM編織是對上面提到的問題最自然的解決方案。為了說明其原因,我們將引入兩個例子,它們說明JVM已經完成了編織所涉及的大多數工作:當載入一個類時,JVM讀取位元組碼,建立為java.lang.reflect.* API進行服務所需的資料;另一個例子是方法排程。目前的JVM將方法或程式碼塊的位元組碼編譯為更高階、效率也更高的構造和執行流(在適用程式碼內聯的地方進行程式碼內聯)。由於HotSwap API的需要,JRockit JVM(可能還包括其他JVM)還會記錄哪個方法呼叫了其他方法,因此如果在執行時重新定義某個類,那麼在所有期望的位置(內聯的或非內聯的),類中定義的方法主體仍然可以進行熱交換。

  因此,不必為了編織進一個建議呼叫而修改位元組碼,比如說,在特定的方法呼叫之前。JVM實際上可以掌握關於這個建議呼叫的知識,它會在任何匹配的聯結點上對此建議進行排程,然後再排程實際的方法。

  由於不接觸位元組碼,立即可以獲得以下好處:

  不會由於位元組碼測試而產生啟動開銷。

  對於在任何位置、任何時間、以遞增式開銷新增和刪除建議的完全的執行時支援。

  對建議的反射式呼叫的隱式支援。

  不需要將類模型複製到特定於框架的某些結構,因此減少了額外的記憶體佔用。

  與JVMDI_EVENT_METHOD_ENTRY或JVMDI_EVENT_FIELD_ACCESS等JVMDI規範中定義的眾所周知的C級別事件相比,這種方式有很大區別。在JVMDI中,必須首先處理C級別API,這使得它對於大多數開發人員來說有些複雜,而且難以分發。其次,規範沒有提供細粒度的聯結點匹配機制,而是要求預定所有這樣的事件。這仍然會導致顯著的開銷,因此不得不進行除錯。

  我們的方法

  我們想讓您先了解一下如何在JVM中新增AOP支援。關鍵之處在於我們在Java API級別上提供了動作排程和預定(下面會詳細描述)。因此,您可以寫出下面這樣的程式碼:

  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);

  如您所見,我們提供了一個可訪問的JVM API,可以用它來實現更傳統的AOP方法。這為解決前面提到的傳統AOP實現問題提供了極大的靈活性,而且也使其他使用方式成為可能。下面幾節將詳細介紹這個API。

  動作排程和預定

  JRockit JVM AOP支援公開了一個Java API,它與JVM方法排程和物件模型元件緊密整合在一起。為了確保不使JVM被限制在當前或未來的任何特定於AOP的技術方向上,我們決定實現一個動作排程和預定模型。

  這個API使您能夠在指定的切點上描述定義良好的預定,這樣就能夠註冊JVM將要排程的動作。動作由以下元件組成:

  一個常規Java方法――我們稱之為動作方法,對於每個匹配這個預定的聯結點,都將呼叫這個方法。

  一個可選的動作例項,在這個例項上呼叫動作方法。

  一組可選的引數級註釋,它們向JVM指出動作方法期望從呼叫堆疊獲得哪些引數。

  動作還可以分為before動作、after returning動作、after throwing動作或者instead-of動作(類似於AOP的“around”概念)。

  為了呼叫這個API,必須獲得一個jrockit.ext.weaving.Weaver例項的控制程式碼。這個編織器例項根據它的呼叫者上下文來控制允許進行哪些操作。例如,在容器級編織器可以預定特定於應用程式的聯結點時,使用者可能不希望部署在應用伺服器中的應用程式建立編織器,從而預定某些容器級或特定於JDK的聯結點的動作方法。這種編織器可見性理念反映了底層類載入器的委託模型。

  我們簡單介紹一下這些構造如何對映到常規的AOP構造,這有助於理解這個模型:

  ?預定可以視為一個有型別的聯結點,或者就是一個有型別的聯結點(欄位get()、set()、方法call()等等),加上一個within()/withincode()切點。

  ?動作例項可以視為方面例項。

  ?動作方法可以視為建議。

  熟悉AOP的讀者可能已經看出,要想用這個JVM級API實現一個完整的AOP框架,還需要進行一些開發,包括一個(按照規定)管理方面例項化模型的中間層、cflow()切點的實現以及切點的完全合成和正交的實現。

  API細節:動作方法

  動作方法(與AOP的建議概念相似)就像(作為方面的)常規類的常規Java方法。它可以是static方法,也可以是成員方法。它的返回型別必須符合某些隱式約定,而且before動作的返回型別應該是void。對於instead-of動作(類似於AOP的around建議語義),其返回型別還是作為動作呼叫結果的堆疊的型別。

  動作方法可以有引數,引數的註釋進一步控制上下文公開,如下面的程式碼示例所示:

  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和類的靜態初始化器(它在java.lang.reflect.*中沒有出現)的包裝器。這與AspectJ JoinPoint.StaticPart.getSignature()抽象化相似。

  下面是當前定義的註釋及其含義。

  
[[The No.1 Picture.]]

  為了支援instead-of,並能夠決定是否沿著擷取鏈前進(就像在AOP中透過JoinPoint.proceed()概念實現),我們引入了jrockit.ext.weaving.InvocationContext構造,如下所示:

  import jrockit.ext.weaving.*;

  public class InsteadOfAction {

  public Object instead(

  InvocationContext jp,

  @CalleeMethod Method callee) {

  return jp.proceed();

  }

  }

  API的細節:動作例項和動作型別

  正如前面程式碼示例中所示,動作方法可以是靜態的,也可以不是。如果動作方法不是靜態的,那麼就必須傳遞一個動作例項,JVM在這個例項上呼叫動作方法。

  其語法風格與Java開發人員使用java.lang.reflect.Method.invoke(null/*static method*/, .../*args*/)對方法進行反射式呼叫一樣。但是,利用JVM的AOP支援,底層的動作呼叫根本不涉及任何反射。

  允許使用者控制動作例項,就會產生有趣的用例。例如,可以實現一個簡單的委託模式,在執行時用另一個實現替換整個動作例項,而不涉及JVM的內部元件。

  注意,這將有助於(按照規定)實現AOP方面例項化模型,比如issingleton()、pertarget()、perthis()、percflow()等等,同時不會將JVM API限制在某些預定義的語義上。

  在將預定註冊到編織器例項之前,賦予它一個型別作為建議型別:before、instead-of、after-returning或after-throwing。

  可以編寫下面這樣的程式碼來建立預定:

  // 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

  );

  MethodSub

--&gtlinux電子圖書免費下載和技術討論基地

·上一篇:
什麼是AOP系列之一:AOP概念解析

·下一篇:JavaEE5.0:使J2EE開發變得容易一些
最新更新
·何種設計模式和構架才能開發出最好的企業程式

·成功規劃面向服務的架構SOA實施

·基於JMX通知框架的AJAX深度開發

·struts+spring+ibatis輕量級J2EE開發

·如何使用動態代理實現AOP功能

·手把手教你使J2EE專案開發自動化

·WeblogicServer9新特性:J2EELibraries

·J2EE核心:iBatisDAO入門與進階二

·J2EE核心:iBatisDAO入門與進階一

·面向方面程式設計的Annotation簡介

·在NetBeansIDE4.1中匯入J2EE應用程式

·NetBeansIDE4.1J2EE程式快速入門指南

·亂碼問題之終極解決

·J2EE專案執行:若干最佳實踐

·為何不讓SOA變得簡單?

·使用WebLogicJMX進行定製除錯

·J2EE工程實現中常見安全問題解決對策

·J2EE的四層模型

·J2EEDesignPatterns

·將J2EE平臺提升到一個新的高度

·CMP實體bean實戰開發

·JNDI設計內幕

·用VisualAgeforJava開發企業級bean

·使用訊息驅動Beans(1)

·使用訊息驅動Beans(2)

·使用訊息驅動Beans(3)

·有狀態會話bean執行結束時應及時被顯示刪除

·最佳化entityBean的七條準則

·使用JSF(JavaServerFaces)開發(一)

·使用JSF(JavaServerFaces)開發(二)


關於我們 | 聯絡方式 | 廣告合作 | 誠聘英才 | 網站地圖 | 網址大全 | 友情連結 |

Copyright © 2004 - 2007 All Rights Reserved

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/8225414/viewspace-968191/,如需轉載,請註明出處,否則將追究法律責任。

相關文章