做者:小傅哥
博客:bugstack.cnjava
❝沉澱、分享、成長,讓本身和他人都能有所收穫!web
❞
在字節碼編程方面有三個比較常見的框架;ASM
、byte-buddy
、Javassist
,他們均可以對這字節碼進行操做,只是操做方式和控制粒度不一樣。編程
其中 「ASM」 更偏向於底層,須要瞭解 「JVM」 虛擬機中指定規範以及對局部變量以及操做數棧的知識。雖然在編寫起來比較麻煩,可是它也是性能最好功能最強的字節碼操做框架。常見的會用在 「CGLIB」 動態代理類中,以及一些非入侵的探針監控場景中。框架
另外兩個框架都是有強大的 API,操做使用上更加容易控制。雖然對對比上會比 「ASM」 性能差一些,但不是說性能徹底很差。一樣在一些監控場景中也用的很是多。若是你細心能夠在你的工程 「jar」 包搜索一下。編輯器
在這以前我已經編寫了 Javaagent全鏈路監控
和 ASM
的部分文章,雖然這部分技術內容在 「CRUD」 開發中並不經常使用,但隨着自動化測試、非入侵監控的大量使用,仍是蠻多人須要這樣的技能學習的。同時我也是這樣一個技能的學習者,爲此後面會陸續編寫和完善關於 「字節碼編程」 這個專欄。也但願這個專欄在提高本身技術棧的同時也幫助他人成長。函數
「那麼」,小傅哥計劃從 Javassist
到 ASM
陸續完成整套專欄學習的文章編寫。從簡單入門到應用操做,一步步來完成成體系的技術知識棧學習。性能
「好!」,如今開始第一個Helloworld案例。相關源碼能夠經過關注 公衆號:bugstack蟲洞棧
獲取學習
<dependency>
<groupId>javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.12.1.GA</version>
<type>jar</type>
</dependency>
複製代碼
不看實現過程的話,咱們的案例目標其實很簡單,就是使用 javassist
輸出一行 Helloworld 。這話像不像產品說的測試
public class HelloWorld {
public static void main(String[] args) {
System.out.println("javassist hi helloworld by 小傅哥(bugstack.cn)");
}
public HelloWorld() {
}
}
複製代碼
以上的這段代碼就是咱們接下來須要使用字節碼編程技術來實現的內容。flex
其實輸出一個 Helloworld
仍是蠻簡單的,主要是從這裏面去學習一下 Javassist
的基本語法結構,也能爲後續的學習有一個基礎的概念。
❝javassist Helloworld
❞
/**
* 公衆號:bugstack蟲洞棧
* 博客棧:https://bugstack.cn - 沉澱、分享、成長,讓本身和他人都能有所收穫!
* 本專欄是小傅哥多年從事一線互聯網Java開發的學習歷程技術彙總,旨在爲你們提供一個清晰詳細的學習教程。若是能爲您提供幫助,請給予支持(關注、點贊、分享)!
*/
public class GenerateClazzMethod {
public static void main(String[] args) throws IOException, CannotCompileException, NotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
ClassPool pool = ClassPool.getDefault();
// 建立類 classname:建立類路徑和名稱
CtClass ctClass = pool.makeClass("org.itstack.demo.javassist.HelloWorld");
// 添加方法
CtMethod mainMethod = new CtMethod(CtClass.voidType, "main", new CtClass[]{pool.get(String[].class.getName())}, ctClass);
mainMethod.setModifiers(Modifier.PUBLIC + Modifier.STATIC);
mainMethod.setBody("{System.out.println(\"javassist hi helloworld by 小傅哥(bugstack.cn)\");}");
ctClass.addMethod(mainMethod);
// 建立無參數構造方法
CtConstructor ctConstructor = new CtConstructor(new CtClass[]{}, ctClass);
ctConstructor.setBody("{}");
ctClass.addConstructor(ctConstructor);
// 輸出類內容
ctClass.writeFile();
// 測試調用
Class clazz = ctClass.toClass();
Object obj = clazz.newInstance();
Method main = clazz.getDeclaredMethod("main", String[].class);
main.invoke(obj, (Object)new String[1]);
}
}
複製代碼
這段代碼分爲幾塊內容來實現功能,分別包括;
ctClass.writeFile()
進行輸出方法的內容信息。也就能夠看到經過咱們使用
Javassist
生成類的樣子。
main
方法,測試輸出結果。
當咱們執行測試的時候會輸出類信息到工程文件夾下,同時會輸出咱們的測試結果;
javassist hi helloworld by 小傅哥(bugstack.cn)
Process finished with exit code 0
複製代碼
Javassist
的使用在完整的且強大的
API
下,確實仍是蠻容易使用的。而且代碼的使用上並非很難理解。