Java 动态代理与class字节码动态修改技术
代理分兩種技術,一種是jdk代理(機制就是反射,只對接口操作),一種就是字節(jié)碼操作技術。前者不能算技術,后者算是新的技術。未來將有大的動作或者較為廣泛的應用和變革,它可以實現(xiàn)代碼自我的編碼(人工智能,代碼智能)。
先看看jvm class技術:
字節(jié)碼改寫:
(一)jdk 動態(tài)代理:
1.定義業(yè)務邏輯
public interface Service { //目標方法 public abstract void add(); } public class UserServiceImpl implements Service { public void add() { System.out.println("This is add service"); } }2. 利用 java.lang.reflect.Proxy 類和 java.lang.reflect.InvocationHandler 接口定義代理類的實現(xiàn)。class MyInvocatioHandler implements InvocationHandler {private Object target;public MyInvocatioHandler(Object target) {this.target = target;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("-----before-----");Object result = method.invoke(target, args);System.out.println("-----end-----");return result;}// 生成代理對象public Object getProxy() {ClassLoader loader = Thread.currentThread().getContextClassLoader();Class<?>[] interfaces = target.getClass().getInterfaces();return Proxy.newProxyInstance(loader, interfaces, this);} }
3.使用動態(tài)代理 public class ProxyTest {public static void main(String[] args) {Service service = new UserServiceImpl();MyInvocatioHandler handler = new MyInvocatioHandler(service);Service serviceProxy = (Service)handler.getProxy();serviceProxy.add();} }
執(zhí)行結果:
-----before----- This is add service -----end----- 代理對象的生成過程由Proxy類的newProxyInstance方法實現(xiàn),分為3個步驟:
1、ProxyGenerator.generateProxyClass方法負責生成代理類的字節(jié)碼,生成邏輯比較復雜,了解原理繼續(xù)分析源碼?sun.misc.ProxyGenerator;
2、native方法Proxy.defineClass0負責字節(jié)碼加載的實現(xiàn),并返回對應的Class對象。
Class clazz = defineClass0(loader, proxyName, proxyClassFile, 0, proxyClassFile.length);3、利用clazz.newInstance反射機制生成代理類的對象;
使用?反編譯工具 jad?jad com.sun.proxy.$Proxy.1?看看代理類如何實現(xiàn),反編譯出來的java代碼如下:
從上述代碼可以發(fā)現(xiàn):
1、生成的$proxy1繼承自Proxy類,并實現(xiàn)了Service接口。
2、執(zhí)行代理對象的方法,其實就是執(zhí)行InvocationHandle對象的invoke方法,傳入的參數(shù)分別是當前代理對象,當前執(zhí)行的方法和參數(shù)。
jdk動態(tài)代理使用的局限性
通過反射類Proxy和InvocationHandler回調接口實現(xiàn)的jdk動態(tài)代理,要求委托類必須實現(xiàn)一個接口,但事實上并不是所有類都有接口,對于沒有實現(xiàn)接口的類,便無法使用該方方式實現(xiàn)動態(tài)代理。
(二)字節(jié)碼修改技術
了解該技術必然先了解Java class文件格式 《讀《深入jvm原理》之class文件》
目前字節(jié)碼修改技術有ASM,javassist等。cglib就是基于封裝的Asm. Spring 就是使用cglib代理庫。
ASM 是一個 Java 字節(jié)碼操控框架。它能夠以二進制形式修改已有類或者動態(tài)生成類。ASM 可以直接產生二進制 class 文件,也可以在類被加載入 Java 虛擬機之前動態(tài)改變類行為。ASM 從類文件中讀入信息后,能夠改變類行為,分析類信息,甚至能夠根據(jù)用戶要求生成新類。
不過ASM在創(chuàng)建class字節(jié)碼的過程中,操縱的級別是底層JVM的匯編指令級別,這要求ASM使用者要對class組織結構和JVM匯編指令有一定的了解。
Java字節(jié)碼生成開源框架介紹--Javassist:
Javassist是一個開源的分析、編輯和創(chuàng)建Java字節(jié)碼的類庫。是由東京工業(yè)大學的數(shù)學和計算機科學系的 Shigeru Chiba (千葉 滋)所創(chuàng)建的。它已加入了開放源代碼JBoss 應用服務器項目,通過使用Javassist對字節(jié)碼操作為JBoss實現(xiàn)動態(tài)AOP框架。javassist是jboss的一個子項目,其主要的優(yōu)點,在于簡單,而且快速。直接使用java編碼的形式,而不需要了解虛擬機指令,就能動態(tài)改變類的結構,或者動態(tài)生成類。
總結
以上是生活随笔為你收集整理的Java 动态代理与class字节码动态修改技术的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 读《深入jvm原理》之class文件
- 下一篇: 说说Javaweb 服务器与Tomcat