要使用Javassist,要先在POM中添加java
<dependency> <groupId>javassist</groupId> <artifactId>javassist</artifactId> <version>3.3</version> </dependency>
咱們先使用Javassist來動態建立一個類,代碼以下app
public class JavassistMain { public static void main(String[] args) throws Exception { //建立ClassPool ClassPool cp = ClassPool.getDefault(); //生成的類的名稱爲com.guanjian.assist.JavassistTest CtClass clazz = cp.makeClass("com.guanjian.assist.JavassistTest"); StringBuffer body = null; //建立字段,指定了字段類型、字段名稱、字段所屬的類 CtField field = new CtField(cp.get("java.lang.String"), "prop", clazz); //指定該字段使用private修飾 field.setModifiers(Modifier.PRIVATE); //設置prop字段的getter/setter方法 clazz.addMethod(CtNewMethod.getter("getProp",field)); clazz.addMethod(CtNewMethod.setter("setProp",field)); //設置prop字段的初始化值,並將prop字段添加到clazz中 clazz.addField(field,CtField.Initializer.constant("MyName")); //建立構造方法,指定了構造方法的參數類型和構造方法所屬的類 CtConstructor ctConstructor = new CtConstructor(new CtClass[]{}, clazz); //設置方法體 body = new StringBuffer(); body.append("{\n prop=\"MyName\";\n}"); ctConstructor.setBody(body.toString()); //將構造方法添加到clazz中 clazz.addConstructor(ctConstructor); //建立execute()方法,指定了方法的返回值、方法名稱、方法參數列表以及方法所屬的類 CtMethod ctMethod = new CtMethod(CtClass.voidType, "execute", new CtClass[]{}, clazz); //指定方法使用public修飾 ctMethod.setModifiers(Modifier.PUBLIC); //設置方法體 body = new StringBuffer(); body.append("{\n System.out.println(\"execute():\" + this.prop);"); body.append("\n}"); ctMethod.setBody(body.toString()); //將execute()方法添加到clazz中 clazz.addMethod(ctMethod); //將上面定義的JavassistTest類保存到指定的目錄 clazz.writeFile("E:\\IOC\\target\\classes"); //加載clazz類,並建立對象 Class<?> c = clazz.toClass(); Object o = c.newInstance(); //調用execute()方法 Method method = o.getClass().getMethod("execute", new Class[]{}); method.invoke(o,new Object[]{}); } }
執行結果:ide
execute():MyNamethis
執行之後咱們能夠在E:\IOC\target\classes\com\guanjian\assist中看見這個.class文件spa
雙擊該class文件,咱們能夠看見它的反編譯的字節碼.net
package com.guanjian.assist; public class JavassistTest { private String prop = "MyName"; public void getProp(String var1) { this.prop = var1; } public String setProp() { return this.prop; } public JavassistTest() { this.prop = "MyName"; } public void execute() { System.out.println("execute():" + this.prop); } }
如今咱們來修改該類,添加一個屬性整形age代理
public class JavassistUpdate { public static void main(String[] args) throws Exception { ClassPool cp = ClassPool.getDefault(); CtClass clazz = cp.get("com.guanjian.assist.JavassistTest"); //建立字段,指定了字段類型、字段名稱、字段所屬的類 CtField field = new CtField(cp.get("java.lang.Integer"), "age", clazz); //指定該字段使用private修飾 field.setModifiers(Modifier.PRIVATE); //設置age字段的getter/setter方法 clazz.addMethod(CtNewMethod.setter("getAge",field)); clazz.addMethod(CtNewMethod.getter("setAge",field)); //將age字段添加到clazz中 clazz.addField(field); clazz.writeFile("E:\\IOC\\target\\classes"); } }
運行後咱們來看一下JavassistTest反編譯的字節碼對象
package com.guanjian.assist; public class JavassistTest { private String prop = "MyName"; private Integer age; public void getProp(String var1) { this.prop = var1; } public String setProp() { return this.prop; } public JavassistTest() { this.prop = "MyName"; } public void execute() { System.out.println("execute():" + this.prop); } public void getAge(Integer var1) { this.age = var1; } public Integer setAge() { return this.age; } }
這個時候咱們能夠看到age屬性被添加了進去blog
前面咱們講過Java動態代理,CGLib動態代理,具體請參考 AOP原理與自實現 繼承
如今來看看Javassist的動態代理
public class JavassistProxy { public static void main(String[] args) throws IllegalAccessException, InstantiationException { ProxyFactory factory = new ProxyFactory(); //指定父類,ProxyFactory會動態生成繼承該父類的子類 //由於沒有.java源文件,此處會飄紅,但有.class文件能夠執行 factory.setSuperclass(JavassistTest.class); //設置過濾器,判斷哪些方法調用須要被攔截 factory.setFilter(new MethodFilter() { @Override public boolean isHandled(Method method) { if (method.getName().equals("execute")) { return true; } return false; } }); //設置攔截處理 factory.setHandler(new MethodHandler() { @Override public Object invoke(Object self, Method thisMethod, Method proceed, Object[] args) throws Throwable { System.out.println("前置處理"); Object result = proceed.invoke(self, args); System.out.println("執行結果:" + result); System.out.println("後置處理"); return result; } }); //建立JavassistTest代理類,並建立代理對象 //由於沒有.java源文件,如下多處會飄紅,但有.class文件能夠執行 Class<?> c = factory.createClass(); JavassistTest javassistTest = (JavassistTest)c.newInstance(); //執行execute()方法,會被攔截 javassistTest.execute(); System.out.println(javassistTest.getProp()); } }
運行結果:
前置處理 execute():MyName 執行結果:null 後置處理 MyName