摘要:因此,若想對對象進行修改,必須對其進行解凍,通過方法進行生成一個方法生成一個方法通過反射調用生成的方法方法體前面和后面加執行語句方法體前面通過反射調用生成的方法張三生成屬性和方法獲取屬性生成構造器可以在構造器前后加代碼注解操作
Java知識點總結(動態字節碼操作-Javassist的API使用)
@(Java知識點總結)[Java, 動態字節碼操作]
參考文章: 傳送
操作示例:
public @interface Author { String name(); int year(); }
@Author(name = "gs",year=2015) public class Emp { private int num; private String name; public Emp() { } public Emp(int num, String name) { this(); this.num = num; this.name = name; } public void sayHello(String name){ System.out.print("你好,"); } public int getNum() { return num; } public void setNum(int num) { this.num = num; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.util.Arrays; import javassist.ClassPool; import javassist.CtClass; import javassist.CtConstructor; import javassist.CtField; import javassist.CtMethod; import javassist.CtNewMethod; import javassist.NotFoundException; /** * 測試 javassist 的 API * * @author Administrator * */ public class Test11 { // 通過類名加載已有的類 public static void test1(ClassPool pool, CtClass cc) { try { cc = pool.get("com.gs.Emp"); byte[] bytes = cc.toBytecode(); // 轉化為字節碼 System.out.println(Arrays.toString(bytes)); System.out.println(cc.getName()); // 獲取類名 System.out.println(cc.getSimpleName()); System.out.println(cc.getSuperclass()); // 獲取父類 System.out.println(cc.getInterfaces()); // 獲取接口 } catch (Exception e) { e.printStackTrace(); } } // 動態生成一個方法,并調用 public static void test2(ClassPool pool, CtClass cc) { try { /*當CtClass對象通過writeFile()、toClass()、toBytecode()轉化為Class后, * Javassist凍結了CtClass對象,因此,JVM不允許再次加載Class文件,所以不允許對其修改。 因此,若想對CtClass對象進行修改,必須對其進行解凍,通過defrost()方法進行*/ cc.defrost(); // 生成一個方法 CtMethod add = CtNewMethod.make("public int add(int a,int b){return $1+$2;}", cc); // 生成一個方法 CtMethod subtraction = new CtMethod(CtClass.intType, "subtraction", new CtClass[] { CtClass.intType, CtClass.intType }, cc); subtraction.setModifiers(Modifier.PUBLIC); subtraction.setBody("return $1-$2;"); cc.addMethod(add); cc.addMethod(subtraction); // 通過反射調用生成的方法 Class clazz = cc.toClass(); Emp emp = (Emp) clazz.newInstance(); // Method method = clazz.getDeclaredMethod("add", new // Class[]{int.class,int.class}); Method method = clazz.getDeclaredMethod("subtraction", new Class[] { int.class, int.class }); Object result = method.invoke(emp, 200, 300); System.out.println(result); } catch (Exception e) { } } // 方法體前面和后面加執行語句 public static void test3(ClassPool pool, CtClass cc) { try { cc.defrost(); CtMethod m1 = cc.getDeclaredMethod("sayHello", new CtClass[] { pool.get("java.lang.String") }); m1.insertBefore("System.out.println("方法體前面");"); m1.insertAfter("System.out.println($1);"); // 通過反射調用生成的方法 Class clazz = cc.toClass(); Emp emp = (Emp) clazz.newInstance(); Method method = clazz.getDeclaredMethod("sayHello", new Class[] { String.class }); method.invoke(emp, "張三"); } catch (Exception e) { e.printStackTrace(); } } // 生成屬性和方法 public static void test4(ClassPool pool, CtClass cc) { try { // CtField.make("private double salary;", cc); CtField field = new CtField(CtClass.doubleType, "salary", cc); field.setModifiers(Modifier.PRIVATE); cc.addField(field); // cc.getDeclaredField("salary"); //獲取屬性 CtMethod method = CtNewMethod.getter("getSalary", field); cc.addMethod(method); CtMethod method2 = CtNewMethod.getter("setSalary", field); cc.addMethod(method2); } catch (Exception e) { e.printStackTrace(); } } // 生成構造器 public static void test5(ClassPool pool, CtClass cc) { try { cc.defrost(); CtConstructor[] cs = cc.getConstructors(); for (CtConstructor c : cs) { System.out.println(c.getLongName()); c.insertAfter("System.out.println("可以在構造器前后加代碼");"); } } catch (Exception e) { e.printStackTrace(); } } // 注解操作 public static void test6(ClassPool pool, CtClass cc) { try { cc.defrost(); Object[] annotations = cc.getAnnotations(); Author author = (Author) annotations[0]; System.out.println("name:" + author.name() + ",year:" + author.year()); } catch (Exception e) { e.printStackTrace(); } } public static void main(String[] args) { ClassPool pool = ClassPool.getDefault(); CtClass cc = null; try { cc = pool.get("com.gs.Emp"); } catch (NotFoundException e) { e.printStackTrace(); } test1(pool, cc); //test2(pool, cc); test3(pool, cc); test5(pool, cc); test6(pool, cc); } }
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/71625.html
摘要:知識點總結動態字節碼操作介紹知識點總結動態字節碼操作運行時操作字節碼可以讓我們實現如下功能動態生成新的類動態改變某個類的結構添加刪除修改新的屬性方法常見的字節碼操作類庫,這是的項目的一部分。 Java知識點總結(動態字節碼操作-Javassist介紹) @(Java知識點總結)[Java, 動態字節碼操作] 運行時操作字節碼可以讓我們實現如下功能: 動態生成新的類 動態改變某個類的結...
摘要:動態編程使用場景通過配置生成代碼,減少重復編碼,降低維護成本。動態生成字節碼操作字節碼的工具有,其中有兩個比較流行的,一個是,一個是。 作者簡介 傳恒,一個喜歡攝影和旅游的軟件工程師,先后從事餓了么物流蜂鳥自配送和蜂鳥眾包的開發,現在轉戰 Java,目前負責物流策略組分流相關業務的開發。 什么是動態編程 動態編程是相對于靜態編程而言的,平時我們討論比較多的靜態編程語言例如Java, 與動態...
摘要:字節碼操作動態性的兩種常見實現方式字節碼操作反射運行時操作字節碼可以讓我們實現如下功能動態生成新的類動態改變某個類的結構添加刪除修改新的屬性方法優勢比反射開銷小性能高性能高于反射低于常見的字節碼操作類庫這是的項目的一部分是廣泛使用的一種框它 1.字節碼操作 JAVA動態性的兩種常見實現方式字節碼操作 反射 運行時操作字節碼可以讓我們實現如下功能動態生成新的類 動態改變某個類的結構(...
摘要:全稱應用性能管理監控后面我會通過一系列的文章來介紹的原理框架設計與實現等等。在應用構建期間,通過修改字節碼的方式來進行字節碼插樁就是實現自動化的方案之一。 showImg(https://segmentfault.com/img/bVbbRX6?w=1995&h=1273); 歡迎關注微信公眾號:BaronTalk,獲取更多精彩好文! 一. 前言 性能問題是導致 App 用戶流失的罪魁...
摘要:支持重試版本思考小明我手頭還有其他任務,這個也挺簡單的。與其他類似的字節碼編輯器不同,提供了兩個級別的源級和字節碼級。另一方面,字節碼級允許用戶直接編輯類文件作為其他編輯器。提供與其他字節碼框架類似的功能,但主要關注性能。 系列說明 java retry 的一步步實現機制。 java-retry 源碼地址 情景導入 簡單的需求 產品經理:實現一個按條件,查詢用戶信息的服務。 小明:好的...
閱讀 3315·2021-11-12 10:36
閱讀 2467·2021-11-02 14:43
閱讀 2146·2019-08-30 14:23
閱讀 3463·2019-08-30 13:08
閱讀 919·2019-08-28 18:09
閱讀 3129·2019-08-26 12:22
閱讀 3141·2019-08-23 18:24
閱讀 2017·2019-08-23 18:17