Java動態編程——Javassist

動態編程是相對於靜態編程而言的,平時咱們討論比較多的就是靜態編程語言,例如Java,與動態編程語言,例如JavaScript。
html

在靜態編程中,類型檢查是在編譯時完成的,而動態編程中類型檢查是在運行時完成的。所謂動態編程就是繞過編譯過程在運行時進行操做的技術,在Java中有以下幾種方式:java


~~~~反射:就是經過在運行時得到類型信息而後作相應的操做。編程


~~~~動態編譯:動態編譯是從Java 6開始支持的,主要是經過一個JavaCompiler接口來完成的。經過這種方式咱們能夠直接編譯一個已經存在的java文件,也能夠在內存中動態生成Java代碼,動態編譯執行。服務器


~~~~調用JavaScript引擎:Java 6加入了對Script(JSR223)的支持。這是一個腳本框架,提供了讓腳本語言來訪問Java內部的方法。你能夠在運行的時候找到腳本引擎,而後調用這個引擎去執行腳本。這個腳本API容許你爲腳本語言提供Java支持。框架


~~~~動態生成字節碼:這種技術經過操做Java字節碼的方式在JVM中生成新類或者對已經加載的類動態添加元素。編程語言


動態編程解決什麼問題ide

在靜態語言中引入動態特性,主要是爲了解決一些使用場景的問題。工具

徹底使用靜態編程也辦的到,只是付出的代價比較高,沒有動態編程來的優雅。例如依賴注入框架Spring使用了反射,而Dagger2 卻使用了代碼生成的方式(APT)。this

如 編碼

一、在那些依賴關係須要動態確認的場景: 

二、須要在運行時動態插入代碼的場景,好比動態代理的實現。 

三、經過配置文件來實現相關功能的場景


Javassist

操做java字節碼的工具BECL/ASM/CGLIB/Javassit

其中有兩個比較流行,一個是ASM,一個是Javassit。


ASM 直接操做字節碼指令,執行效率高,要是使用者掌握Java類字節碼文件格式及指令,對使用者的要求比較高。

Javassit 提供了更高級的API,執行效率相對較差,但無需掌握字節碼指令的知識,對使用者要求較低。

Javassit 是一個開源的分析、編輯和建立Java字節碼的類庫。是由東京工業大學的數學和計算機科學系的 Shigeru Chiba (千葉 滋)所建立的。它已加入了開放源代碼JBoss應用服務器項目,經過使用Javassist對字節碼操做爲JBoss實現動態AOP框架。javassist是jboss的一個子項目,其主要的優勢,在於簡單,並且快速。直接使用java編碼的形式,而不須要了解虛擬機指令,就能動態改變類的結構,或者動態生成類。


Javassist中最爲重要的是ClassPool,CtClass ,CtMethod 以及 CtField這幾個類。


ClassPool:一個基於HashMap實現的CtClass對象容器,其中鍵是類名稱,值是表示該類的CtClass對象。默認的ClassPool使用與底層JVM相同的類路徑,所以在某些狀況下,可能須要向ClassPool添加類路徑或類字節。


CtClass:表示一個類,這些CtClass對象能夠從ClassPool得到。


CtMethods:表示類中的方法。


CtFields :表示類中的字段。


例子:

建立Class,Field,Method,Constructor

    public static void main(String[] args) throws Exception {
        ClassPool pool = ClassPool.getDefault();
        CtClass person = pool.makeClass("com.temp.bytecodeop.Person");
        
        //建立屬性
        CtField name = CtField.make("private String name;", person);
        CtField age = CtField.make("private int age;", person);
        person.addField(name);
        person.addField(age);
        
        //建立方法
        CtMethod getName = CtMethod.make("public String getName(){return name;}", person);
        CtMethod setName = CtMethod.make("public void setName(String name){this.name=name;}", person);
        person.addMethod(getName);
        person.addMethod(setName);
        
        //建立構造器        
        CtConstructor constructor = new CtConstructor(new CtClass[]{pool.get("java.lang.String"),CtClass.intType},person);
        constructor.setBody("{this.name=name; this.age=age;}");
        person.addConstructor(constructor);
        
        person.writeFile("c:/Person");
        System.out.println("success");
    }




參考文獻:https://blog.csdn.net/ShuSheng0007/article/details/81269295

https://www.cnblogs.com/sunfie/p/5154246.html

相關文章
相關標籤/搜索