深入位元組碼 -- 使用 ASM 實現 AOP
轉自:http://my.oschina.net/u/1166271/blog/162796?fromerr=Z7KbK3cz
AOP 的概念已經不是什麼新鮮事物,所以我在這裡就不在介紹 Aop 的概念。目前市面上要做到 Aop 是一件十分簡單的事情。Spring、AspectJ、CGLib等等都可以幫助你達到目的,但是它們也只不過是一些泛生品。
上面提到了一些開源的 Aop 實現技術選型,但是我敢說無論你嘗試使用上面哪種技術選型都沒有我將要介紹的這種方式的執行效率最高。不過讀者不要高興的太早,讀完本文想必你就知道是什麼原因了。
ASM 是一個 Java 位元組碼操控框架。它能被用來動態生成類或者增強既有類的功能。ASM 可以直接產生二進位制 class 檔案,也可以在類被載入入 Java 虛擬機器之前動態改變類行為。Java class 被儲存在嚴格格式定義的 .class 檔案裡,這些類檔案擁有足夠的元資料來解析類中的所有元素:類名稱、方法、屬性以及 Java 位元組碼(指令)。ASM 從類檔案中讀入資訊後,能夠改變類行為,分析類資訊,甚至能夠根據使用者要求生成新類。
可以負責任的告訴大家,ASM只不過是通過 “Visitor” 模式將 “.class” 類檔案的內容從頭到尾掃描一遍。因此如果你抱著任何更苛刻的要求最後都將失望而歸。上面我們介紹的那些 Aop 框架它們幾乎都屬於 ASM 框架的泛生品。
眾所周知,Aop 無論概念有多麼深奧。它無非就是一個“Propxy模式”。被代理的方法在呼叫前後作為代理程式可以做一些預先和後續的操作。這一點想必讀者都能達到一個共識。因此要想實現 Aop 的關鍵是,如何將我們的程式碼安插到被呼叫方法的相應位置。
而要追求 Aop 最快的效率的方法也正式將我們要執行的程式碼直接安插到相應的位置。先看一段最簡單的程式碼。
1 2 3 4 5 |
public
class
TestBean {
public
void
halloAop() {
System.out.println( "Hello
Aop" );
}
}
|
接下來我要為 halloAop 這個方法加裝一個Aop,使在它之前和之後各列印一段字串。最後的程式碼執行起來看上去應該是這個樣子的:
?1 2 3 4 5 6 7 |
public
class
TestBean {
public
void
halloAop() {
System.out.println( "before" );
System.out.println( "Hello
Aop" );
System.out.println( "after" );
}
}
|
首先使用 javac 上面類,然後通過javap -c 檢視它們的程式碼:
?1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
$
javap -c TestBean
Compiled
from "TestBean.java"
public
class
|