自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

字節(jié)碼增強(qiáng)技術(shù),不止有 Java Proxy、 Cglib 和 Javassist 還有 Byte Buddy

開(kāi)發(fā) 前端
根據(jù) Byte Buddy? 官網(wǎng)所說(shuō),Byte Buddy? 是一個(gè)代碼生成和操作庫(kù),用于在 Java? 應(yīng)用程序運(yùn)行時(shí)創(chuàng)建和修改 Java 類(lèi),而無(wú)需編譯器的幫助。

提到字節(jié)碼增強(qiáng)技術(shù),相信用過(guò) Spring 的小伙伴都會(huì)知道 Java Proxy 和 Cglib。

畢竟面試準(zhǔn)備的八股文中說(shuō)過(guò),Spring 的動(dòng)態(tài)代理有兩種實(shí)現(xiàn)方式,在有接口存在的時(shí)候使用 Java Proxy,當(dāng)沒(méi)有接口的時(shí)候使用的是 Cglib。

這兩種方式的區(qū)別不在本文的討論范圍之內(nèi),今天想給大家介紹了是另一個(gè)字節(jié)碼增強(qiáng)技術(shù) Byte Buddy。

Byte Buddy

根據(jù) Byte Buddy 官網(wǎng)所說(shuō),Byte Buddy 是一個(gè)代碼生成和操作庫(kù),用于在 Java 應(yīng)用程序運(yùn)行時(shí)創(chuàng)建和修改 Java 類(lèi),而無(wú)需編譯器的幫助。

Byte Buddy 提供一套簡(jiǎn)單易用的 API,可以很方便的使用 Java 流式編程的形式來(lái)動(dòng)態(tài)創(chuàng)建類(lèi)或者創(chuàng)建接口的實(shí)現(xiàn)類(lèi),這一點(diǎn)跟 Java Proxy 和 Cglib 不一樣。

使用 Byte Buddy 的方式也非常簡(jiǎn)單,只要直接引入 Maven 依賴(lài)即可,沒(méi)有其他繁瑣的依賴(lài)??偟膩?lái)說(shuō),使用 Byte Buddy 有下面的優(yōu)勢(shì):

  1. 無(wú)需理解字節(jié)碼格式,簡(jiǎn)單易用的 API 能很容易操作字節(jié)碼;
  2. 支持 Java 任何版本,庫(kù)輕量,僅取決于 Java 字節(jié)代碼解析器庫(kù) ASM 的訪問(wèn)者 API,它本身不需要任何其他依賴(lài)項(xiàng)。
  3. 比起 JDK 動(dòng)態(tài)代理、cglib、Javassist,Byte Buddy 在性能上具有優(yōu)勢(shì)。

圖片圖片

這一份測(cè)試報(bào)告是官網(wǎng)提供的,表中的每一行分別為,類(lèi)的創(chuàng)建、接口實(shí)現(xiàn)、方法調(diào)用、類(lèi)型擴(kuò)展、父類(lèi)方法調(diào)用的性能結(jié)果。

從性能報(bào)告中可以看出,Byte Buddy 在一些場(chǎng)景是有優(yōu)勢(shì)的,但是在有些場(chǎng)景也不見(jiàn)得特別有優(yōu)勢(shì),不過(guò)整體來(lái)看還是不錯(cuò)的。

測(cè)試

說(shuō)了那么多,下面給大家演示一下,如果使用 Byte Buddy,首先我們需要引入 Maven 依賴(lài),我這里用的版本是 1.14.6,也可以使用其他版本。

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

創(chuàng)建一個(gè)類(lèi),并覆蓋 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);
        }
    }

整個(gè)代碼的思路是通過(guò) Byte Buddy,構(gòu)造出一個(gè) Class 對(duì)象,然后調(diào)用 Class 對(duì)象的 newInstance() 方法,再執(zhí)行 toString() 方法。上面兩個(gè)方式的功能是一樣的,寫(xiě)出來(lái)更方便大家理解。

其中各個(gè)方法的含義如下:

subClass:表示構(gòu)造的類(lèi)是 Object 的子類(lèi);

method:表示要構(gòu)造的具體方法,類(lèi)似于過(guò)濾的功能;

intercept:表示對(duì)過(guò)濾后的方法進(jìn)行攔截;

FixedValue.value("Hello World!"):表示構(gòu)造返回一個(gè)”Hello World!“ 字符串;

make:創(chuàng)建 DynamicType.Unloaded 對(duì)象,此時(shí)這個(gè)對(duì)象被構(gòu)造出來(lái),但是還沒(méi)有被 JVM 加載,還不能使用;

load,getLoaded:加載當(dāng)前類(lèi)的構(gòu)造器,并進(jìn)行加載;

等到加載到 JVM 過(guò)后,就可以使用 newInstance().toString() 進(jìn)行調(diào)用了。

代理方法

上面的例子是創(chuàng)建一個(gè)簡(jiǎn)單的類(lèi)和方法,下面我們介紹一個(gè)代理方法的使用,這里我們有一個(gè)目標(biāo)類(lèi) Target 和一個(gè)方法 saySomething() 方法,有一個(gè)代理類(lèi) Agent,里面有一個(gè)代理方法 agentSaySomething(),如下所示:

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 字節(jié)碼寫(xiě)入文件中
            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("類(lèi)輸出路徑:" + 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();
    }

運(yùn)行過(guò)后我們可以看到生成了一個(gè) class 文件,通過(guò)查看代碼如下,可以看到是創(chuàng)建了一個(gè) Target 的子類(lèi),并且調(diào)用了 Agent 的 agentSaySomething 方法。

圖片圖片

總結(jié)

Byte Buddy的 API 很豐富,這里只是很簡(jiǎn)單的給大家使用了幾個(gè) API,還有包括方法,字段的設(shè)定等等,感興趣的小伙伴可以繼續(xù)去學(xué)習(xí)學(xué)習(xí)。

責(zé)任編輯:武曉燕 來(lái)源: Java極客技術(shù)
相關(guān)推薦

2023-03-27 16:44:23

2023-02-09 08:24:02

javassist字節(jié)碼學(xué)習(xí)

2023-09-11 19:53:50

2019-10-30 08:45:21

JS代碼NodeJS

2023-01-01 14:04:51

字節(jié)碼接口系統(tǒng)

2011-12-01 14:56:30

Java字節(jié)碼

2015-08-17 11:30:51

2010-09-25 10:20:05

JAVA字節(jié)碼

2021-12-09 22:36:30

Java 字節(jié)碼頁(yè)緩存

2020-10-25 17:11:29

JDK代理監(jiān)控

2022-07-18 10:39:49

物聯(lián)網(wǎng)AR

2021-12-27 09:52:43

數(shù)據(jù)庫(kù)優(yōu)化SQL

2023-07-03 08:11:48

java字節(jié)碼字段

2018-12-06 10:22:54

Linux內(nèi)核內(nèi)存

2022-03-30 10:10:17

字節(jié)碼棧空間

2023-03-31 08:22:48

javassitcglibAOP

2020-02-11 14:14:52

this函數(shù)

2019-12-20 12:38:28

Java技術(shù)工具

2020-12-11 08:04:22

SpringAOPBean

2013-11-22 17:42:14

SAP中國(guó)商業(yè)同略會(huì)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)