要使用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