AVt天堂网 手机版,亚洲va久久久噜噜噜久久4399,天天综合亚洲色在线精品,亚洲一级Av无码毛片久久精品

當前位置:首頁 > 科技  > 軟件

字節碼增強技術,不止有 Java Proxy、 Cglib 和 Javassist 還有 Byte Buddy

來源: 責編: 時間:2024-02-01 12:51:52 253觀看
導讀提到字節碼增強技術,相信用過 Spring 的小伙伴都會知道 Java Proxy 和 Cglib。畢竟面試準備的八股文中說過,Spring 的動態代理有兩種實現方式,在有接口存在的時候使用 Java Proxy,當沒有接口的時候使用的是 Cglib。這兩種

提到字節碼增強技術,相信用過 Spring 的小伙伴都會知道 Java Proxy 和 Cglib。iXN28資訊網——每日最新資訊28at.com

畢竟面試準備的八股文中說過,Spring 的動態代理有兩種實現方式,在有接口存在的時候使用 Java Proxy,當沒有接口的時候使用的是 Cglib。iXN28資訊網——每日最新資訊28at.com

這兩種方式的區別不在本文的討論范圍之內,今天想給大家介紹了是另一個字節碼增強技術 Byte Buddy。iXN28資訊網——每日最新資訊28at.com

Byte Buddy

根據 Byte Buddy 官網所說,Byte Buddy 是一個代碼生成和操作庫,用于在 Java 應用程序運行時創建和修改 Java 類,而無需編譯器的幫助。iXN28資訊網——每日最新資訊28at.com

Byte Buddy 提供一套簡單易用的 API,可以很方便的使用 Java 流式編程的形式來動態創建類或者創建接口的實現類,這一點跟 Java Proxy 和 Cglib 不一樣。iXN28資訊網——每日最新資訊28at.com

使用 Byte Buddy 的方式也非常簡單,只要直接引入 Maven 依賴即可,沒有其他繁瑣的依賴。總的來說,使用 Byte Buddy 有下面的優勢:iXN28資訊網——每日最新資訊28at.com

  1. 無需理解字節碼格式,簡單易用的 API 能很容易操作字節碼;
  2. 支持 Java 任何版本,庫輕量,僅取決于 Java 字節代碼解析器庫 ASM 的訪問者 API,它本身不需要任何其他依賴項。
  3. 比起 JDK 動態代理、cglib、Javassist,Byte Buddy 在性能上具有優勢。

圖片圖片iXN28資訊網——每日最新資訊28at.com

這一份測試報告是官網提供的,表中的每一行分別為,類的創建、接口實現、方法調用、類型擴展、父類方法調用的性能結果。iXN28資訊網——每日最新資訊28at.com

從性能報告中可以看出,Byte Buddy 在一些場景是有優勢的,但是在有些場景也不見得特別有優勢,不過整體來看還是不錯的。iXN28資訊網——每日最新資訊28at.com

測試

說了那么多,下面給大家演示一下,如果使用 Byte Buddy,首先我們需要引入 Maven 依賴,我這里用的版本是 1.14.6,也可以使用其他版本。iXN28資訊網——每日最新資訊28at.com

<dependency>    <groupId>net.bytebuddy</groupId>    <artifactId>byte-buddy</artifactId>    <version>1.14.6</version></dependency>

創建一個類,并覆蓋 toString

public static void test1() {        try {            Class<?> dynamicType = new ByteBuddy().                    subclass(Object.class)                    .method(ElementMatchers.named("toString"))                    .intercept(FixedValue.value("Hello World!"))                    .make()                    .load(ByteBuddyDemo.class.getClassLoader())                    .getLoaded();            System.out.println(dynamicType.newInstance().toString());        } catch (Exception e) {            System.out.println(e.getMessage());        }    }public static void test2() {        try {            DynamicType.Unloaded<Object> unloaded = new ByteBuddy()                    .subclass(Object.class)                    .method(ElementMatchers.named("toString"))                    .intercept(FixedValue.value("Hello World!"))                    .make();            DynamicType.Loaded<Object> load = unloaded.load(ByteBuddyDemo.class.getClassLoader());            System.out.println(load.getLoaded().newInstance().toString());        } catch (Exception e) {            throw new RuntimeException(e);        }    }

整個代碼的思路是通過 Byte Buddy,構造出一個 Class 對象,然后調用 Class 對象的 newInstance() 方法,再執行 toString() 方法。上面兩個方式的功能是一樣的,寫出來更方便大家理解。iXN28資訊網——每日最新資訊28at.com

其中各個方法的含義如下:iXN28資訊網——每日最新資訊28at.com

subClass:表示構造的類是 Object 的子類;iXN28資訊網——每日最新資訊28at.com

method:表示要構造的具體方法,類似于過濾的功能;iXN28資訊網——每日最新資訊28at.com

intercept:表示對過濾后的方法進行攔截;iXN28資訊網——每日最新資訊28at.com

FixedValue.value("Hello World!"):表示構造返回一個”Hello World!“ 字符串;iXN28資訊網——每日最新資訊28at.com

make:創建 DynamicType.Unloaded 對象,此時這個對象被構造出來,但是還沒有被 JVM 加載,還不能使用;iXN28資訊網——每日最新資訊28at.com

load,getLoaded:加載當前類的構造器,并進行加載;iXN28資訊網——每日最新資訊28at.com

等到加載到 JVM 過后,就可以使用 newInstance().toString() 進行調用了。iXN28資訊網——每日最新資訊28at.com

代理方法

上面的例子是創建一個簡單的類和方法,下面我們介紹一個代理方法的使用,這里我們有一個目標類 Target 和一個方法 saySomething() 方法,有一個代理類 Agent,里面有一個代理方法 agentSaySomething(),如下所示:iXN28資訊網——每日最新資訊28at.com

public class Target {    public String saySomething() {        return "Hello target";    }}public class Agent {    public static String agentSaySomething() {        System.out.println("agentSaySomething");        return "hello agent";    }}public static void test4() {        try {            DynamicType.Unloaded<Target> agent = new ByteBuddy()                    .subclass(Target.class)                    .method(named("saySomething")                            .and(isDeclaredBy(Target.class)                                    .and(returns(String.class))))                    .intercept(MethodDelegation.to(Agent.class))                    .make();            // 將 agent 字節碼寫入文件中            outputClazz(agent.getBytes());        } catch (Exception e) {            throw new RuntimeException(e);        }    }    private static void outputClazz(byte[] bytes) {        FileOutputStream out = null;        try {            String pathName = ByteBuddyDemo.class.getResource("/").getPath() + "AgentTarget.class";            out = new FileOutputStream(new File(pathName));            System.out.println("類輸出路徑:" + pathName);            out.write(bytes);        } catch (Exception e) {            e.printStackTrace();        } finally {            if (null != out) try {                out.close();            } catch (IOException e) {                e.printStackTrace();            }        }    }   public static void main(String[] args) {        test4();    }

運行過后我們可以看到生成了一個 class 文件,通過查看代碼如下,可以看到是創建了一個 Target 的子類,并且調用了 Agent 的 agentSaySomething 方法。iXN28資訊網——每日最新資訊28at.com

圖片圖片iXN28資訊網——每日最新資訊28at.com

總結

Byte Buddy的 API 很豐富,這里只是很簡單的給大家使用了幾個 API,還有包括方法,字段的設定等等,感興趣的小伙伴可以繼續去學習學習。iXN28資訊網——每日最新資訊28at.com

本文鏈接:http://www.tebozhan.com/showinfo-26-70468-0.html字節碼增強技術,不止有 Java Proxy、 Cglib 和 Javassist 還有 Byte Buddy

聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com

上一篇: Spring Boot項目集成RabbitMQ實戰以及坑點講解

下一篇: Java的ConcurrentHashMap是使用的分段鎖?

標簽:
  • 熱門焦點
Top