動態編程是相對於靜態編程而言的,平時咱們討論比較多的就是靜態編程語言,例如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