日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

查看动态代理生成的代理类字节码

發(fā)布時間:2024/9/30 编程问答 38 豆豆
生活随笔 收集整理的這篇文章主要介紹了 查看动态代理生成的代理类字节码 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

文章目錄

  • 動態(tài)代理的知識介紹
  • 用java proxy實現(xiàn)動態(tài)代理
    • 查看生成的class代理類字節(jié)碼
    • 創(chuàng)建代理的源碼

動態(tài)代理的知識介紹

一、動態(tài)代理和Class字節(jié)碼的關系

動態(tài)代理有什么作用及應用場景?
  1.日志集中打印
  2.事務
  3.權限管理
  4.AOP

在Spring Aop當中可以哪些方式實現(xiàn),及區(qū)別?
  l.java Proxy(動態(tài)構建字節(jié)碼)(動態(tài)構建全新字節(jié)碼bean初始化的時候)
  2.cglib(動態(tài)構建字節(jié)碼)(動態(tài)構建全新字節(jié)碼bean初始化的時候)
  3.Aspecti(修改目標類的字節(jié),織入代理的字節(jié),在程序編譯(編譯的時候插入動態(tài)代理的字節(jié)碼,不會生成全新的Class)
  4.instrumentation(修改目標類的字節(jié)碼、類裝載的時候動態(tài)攔截去修改,基于iavaagent)-javaagent:spring-instrument-4.3.8.RELEASE.jar(類裝載的時候插入動態(tài)代理的字節(jié)碼,不會生成全新的Class)

關于實現(xiàn)動態(tài)代理的技術

1.動態(tài)代理可以由java proxy、cglib、instrumentation(javaagent)、Aspectj、等多種方式實現(xiàn)
  2.動態(tài)代理本質是對class字節(jié)碼進行動態(tài)構建或修改。
  3.修改的工具有ASM、javavssist
  4.多種實現(xiàn)方式的區(qū)別在于對字節(jié)碼切入方式不一樣。可選方式的有:

java proxy、Cglib是基于動態(tài)構建接口實現(xiàn)類字節(jié)

AspectJ是借助Eclipse工具在編譯時織入代理字節(jié)

instrumentation是基于javaagent在類裝載時修改Class織入代理字節(jié)

使用字定義ClassLoader在裝載時織入代理字節(jié)JAVA Proxy實現(xiàn)過程
動態(tài)代理技術棧圖:

用java proxy實現(xiàn)動態(tài)代理

一個簡單實現(xiàn)的例子:

public interface User {String getName(String name); }```java public class Userimpl implements User{@Overridepublic String getName(String name) {System.out.println("實現(xiàn)類");return name;} } ```java public class UserProxy {public static void main(String[] args) {final Userimpl userimpl = new Userimpl();User targetproxy = (User) Proxy.newProxyInstance(UserProxy.class.getClassLoader(), new Class[]{User.class}, new InvocationHandler() {@Overridepublic Object invoke(Object proxy, Method method, Object[] myargs) throws Throwable {System.out.println("q我是前置");try {return method.invoke(userimpl,myargs);} finally {System.out.println("后置");}}}); targetproxy.getName("hzy");} }

查看生成的class代理類字節(jié)碼

public static void buildProxy() throws IOException {byte[] bytes = ProxyGenerator.generateProxyClass("User$proxy",new Class[]{User.class});String fileName = System.getProperty("user.dir")+"\\target\\UserService$proxy.class";File file = new File(fileName);FileOutputStream fileOutputStream = new FileOutputStream(file);fileOutputStream.write(bytes);fileOutputStream.flush();fileOutputStream.close();}

在上面的main函數中加上 buildProxy()方法,執(zhí)行后查看文件目錄:

可以看到生成的class文件
把文件拖到idea里面,可以看到反編譯后的文件:

創(chuàng)建代理的源碼

首先是newProxyInstance方法:

可以看到進入了這句 Class<?> cl = getProxyClass0(loader, intfs);//尋找或者生成目標代理類

private static Class<?> getProxyClass0(ClassLoader loader,Class<?>... interfaces) {if (interfaces.length > 65535) {throw new IllegalArgumentException("interface limit exceeded");}// If the proxy class defined by the given loader implementing// the given interfaces exists, this will simply return the cached copy;// otherwise, it will create the proxy class via the ProxyClassFactoryreturn proxyClassCache.get(loader, interfaces);}

這個注釋的意思:如果由實現(xiàn)給定接口的給定加載器定義的代理類存在,這將簡單地返回緩存副本;否則,它將通過 ProxyClassFactory 創(chuàng)建代理類,即判斷這個接口是不是已經裝載class,如果有則直接返回

之后還有apply方法、proxyfactory中的方法等等,比較復雜,以后再仔細學。

總結

以上是生活随笔為你收集整理的查看动态代理生成的代理类字节码的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。