最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

詳解Java中Javassist的使用

 更新時間:2023年04月03日 16:41:52   作者:胡安民  
常用的一些操作字節(jié)碼的技術(shù)有?ASM、AspectJ、Javassist?等。本文主要為大家介紹了Javassist使用的相關(guān)知識,感興趣的小伙伴可以了解一下

開篇

說起 AOP 小伙伴們肯定很熟悉,無論是 JDK 動態(tài)代理或者是 CGLIB 等,其底層都是通過操作 Java 字節(jié)碼來實現(xiàn)代理。常用的一些操作字節(jié)碼的技術(shù)有 ASM、AspectJ、Javassist 等。

ASM 其設(shè)計和實現(xiàn)是盡可能小而且快,更專注于性能。它在指令的層面來操作,所以使用它需要對 JVM 的指令有所了解,門檻較高,CGLIB 就使用了 ASM 技術(shù)。

AspectJ 擴展了 Java 語言,定義了一系列 AOP 語法,在 JVM 中運行需要使用特定的編譯器生成遵守 Java 字節(jié)碼規(guī)范的 Class 文件,Spring AOP 使用了 AspectJ 。

Javassist 直接使用 Java 編碼的形式操作字節(jié)碼,簡單易上手,性能高于反射,相比于 ASM 稍低。

Javassist 常用類

Javassist 抽象出一個 ClassPool 對象來操作 Java 類,可以通過 ClassPool.getDefault() 來獲取默認的 ClassPool 。常用的對象:

CtClass:代表一個 Class 的實例,可以通過類的全限定名來獲取 CtClass 對象,其中包含了對 Class 的各種操作。

ClassPool:通過 HashTable 保存了路徑下的 CtClass 信息,key為類的全限定名稱,value 為類名對應(yīng)的 CtClass 對象。

CtMethod、CtField:抽象出類的方法和屬性,可以用于定義或修改方法和字段。

Javassist 的使用

依賴

<dependency>
  <groupId>org.javassist</groupId>
  <artifactId>javassist</artifactId>
  <version>3.27.0-GA</version>
</dependency>

代碼示例

// 獲取默認類池
  ClassPool classPool = ClassPool.getDefault();
  // 1. 創(chuàng)建空類
  CtClass ctClass = classPool.makeClass("com.aysaml.demo.javassist.User");

  // 2. 創(chuàng)建 String 類型的 name 字段
  CtField field = new CtField(classPool.get("java.lang.String"), "name", ctClass);
  // 設(shè)置字段訪問級別 private
  field.setModifiers(Modifier.PRIVATE);
  // 增加字段
  ctClass.addField(field);

  // 3. 增加 getter & setter 方法
  ctClass.addMethod(CtNewMethod.getter("getName", field));
  ctClass.addMethod(CtNewMethod.setter("setName", field));

  // 4. 增加無參構(gòu)造方法:其中 $0 表示 this,$1 表示參數(shù)
  CtConstructor noArgsCons = new CtConstructor(new CtClass[] {}, ctClass);
  noArgsCons.setBody("{$0.name=\"mark\";}");
  ctClass.addConstructor(noArgsCons);

  // 5. 增加有參構(gòu)造方法
  CtConstructor hasArgsCons =
    new CtConstructor(new CtClass[] {classPool.get("java.lang.String")}, ctClass);
  hasArgsCons.setBody("{$0.name=$1;}");
  ctClass.addConstructor(hasArgsCons);

  // 6. 創(chuàng)建方法
  CtMethod method = new CtMethod(CtClass.voidType, "printName", new CtClass[] {}, ctClass);
  method.setBody("{System.out.println($0.name);}");
  ctClass.addMethod(method);

  // 7. 生成類文件:可指定路徑,默認為當(dāng)前項目根目錄
  ctClass.writeFile();

  // 8. 創(chuàng)建類實例
  Object person = ctClass.toClass().newInstance();

如何實現(xiàn)類似 AOP 的功能

javassist 對于編程化的操作字節(jié)碼是很簡單易懂的,我們以在方法的開頭結(jié)尾打印信息為例:

public class Cat {

 /** 記錄喵喵喵的次數(shù) */
 private int num;

 public void miao() {
  this.num++;
 }
}

我們要在 miao( ) 方法的前增加聲音輸出:

public static void main(String[] args) throws NotFoundException, CannotCompileException {
  ClassPool classPool = ClassPool.getDefault();
  // 獲取 Cat 類的 CtClass 對象
  CtClass catClass = classPool.get("com.aysaml.demo.javassist.Cat");
  // 獲取 miao( ) 方法
  CtMethod method = catClass.getDeclaredMethod("miao");
  method.insertBefore("System.out.println(\"miao~\");");
  // 加載修改過的類,注意必須要保證調(diào)用前這個類沒有被加載過
  catClass.toClass();
  //測試
  Cat cat = new Cat();
  cat.miao();
 }

注意到,在使用 catClass.toClass() 加載被修改過的類時,強調(diào)必須保證在調(diào)用前這個類沒有被加載過,否則會報 attempted duplicate class definition for name 異常。

我們知道一個類是不能被一個類加載器加載兩次的,所以為了解決這個問題,需要制定一個沒有加載過該類的 Classloader,Javassist 提供了一個 ClassLoader ,如下:

public class Cat {

 /** 記錄喵喵喵的次數(shù) */
 private int num;

 public void miao() {
  System.out.println("調(diào)用了 miao 方法");
  this.num++;
 }

 public static void main(String[] args) throws Exception{
  ClassPool classPool = ClassPool.getDefault();
  // 獲取 Cat 類的 CtClass 對象
  CtClass catClass = classPool.get("com.aysaml.demo.javassist.Cat");
  // 獲取 miao( ) 方法
  CtMethod method = catClass.getDeclaredMethod("miao");
  method.insertBefore("System.out.println(\"miao~\");");
  // 重新設(shè)置一個 Classloader
  Loader classLoader = new Loader(classPool);
  Class clazz = classLoader.loadClass("com.aysaml.demo.javassist.Cat");
  // 調(diào)用修改過的類的方法
  clazz.getDeclaredMethod("miao").invoke(clazz.newInstance());
 }
}

執(zhí)行結(jié)果為:

到此這篇關(guān)于詳解Java中Javassist的使用的文章就介紹到這了,更多相關(guān)Java Javassist內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java編程異常處理最佳實踐【推薦】

    Java編程異常處理最佳實踐【推薦】

    這篇文章主要介紹了Java編程異常處理最佳實踐【推薦】,具有一定參考價值,需要的朋友可以了解下。
    2017-10-10
  • Springboot項目刪除項目同步target文件問題解決方案

    Springboot項目刪除項目同步target文件問題解決方案

    這篇文章主要介紹了Springboot項目刪除項目同步target文件問題解決方案,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2020-12-12
  • spring security與corsFilter沖突的解決方案

    spring security與corsFilter沖突的解決方案

    這篇文章主要介紹了spring security與corsFilter沖突的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-11-11
  • Maven之遠程倉庫的配置詳解

    Maven之遠程倉庫的配置詳解

    這篇文章主要介紹了Maven之遠程倉庫的配置詳解,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-09-09
  • Spring Security OAuth2 token權(quán)限隔離實例解析

    Spring Security OAuth2 token權(quán)限隔離實例解析

    這篇文章主要介紹了Spring Security OAuth2 token權(quán)限隔離實例解析,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-11-11
  • Java中的命名與目錄接口JNDI基本操作方法概覽

    Java中的命名與目錄接口JNDI基本操作方法概覽

    這篇文章主要介紹了Java中的命名與目錄接口JNDI基本操作方法概覽,JNDI提供統(tǒng)一的客戶端API使得Java應(yīng)用程序可以和這些命名服務(wù)和目錄服務(wù)之間進行交互,需要的朋友可以參考下
    2016-03-03
  • Java中與數(shù)字相關(guān)的常用類的用法詳解

    Java中與數(shù)字相關(guān)的常用類的用法詳解

    在我們的代碼中,經(jīng)常會遇到一些數(shù)字&數(shù)學(xué)問題、隨機數(shù)問題、日期問題和系統(tǒng)設(shè)置問題等,為了解決這些問題,Java給我們提供了多個處理相關(guān)問題的類,比如Number類、Math類、Random類等等,本篇文章我們先從Number數(shù)字類和Math數(shù)學(xué)類學(xué)起
    2023-05-05
  • 解決idea中servlet報紅問題

    解決idea中servlet報紅問題

    這篇文章主要介紹了解決idea中servlet報紅問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-04-04
  • SpringData JPA 如何搭建 xml的配置方式

    SpringData JPA 如何搭建 xml的配置方式

    這篇文章主要介紹了SpringData JPA 如何搭建 xml的配置方式,本文通過實例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友參考下吧
    2023-12-12
  • Intellij Idea 多模塊Maven工程中模塊之間無法相互引用問題

    Intellij Idea 多模塊Maven工程中模塊之間無法相互引用問題

    這篇文章主要介紹了Intellij Idea 多模塊Maven工程中模塊之間無法相互引用問題,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-01-01

最新評論

于田县| 山阴县| 文山县| 盈江县| 闽清县| 芮城县| 岑巩县| 永和县| 大邑县| 富平县| 黄梅县| 从化市| 安新县| 石楼县| 陆良县| 永顺县| 抚顺市| 南部县| 潜山县| 汾阳市| 颍上县| 邳州市| 安岳县| 宁德市| 桐城市| 无锡市| 青神县| 南皮县| 乐清市| 隆林| 隆安县| 松阳县| 尚志市| 阜宁县| 正安县| 朝阳县| 昌邑市| 黄石市| 湄潭县| 丰都县| 茶陵县|