Java字节码生成开源框架有Javassist,ASM Javassist已经加入了JBoss,JBoss用此实现了其动态AOP框架
ASM操作级别是底层JVM的汇编指令级别,这要求ASM使用者要对class组织结构和JVM汇编指令有一定的了解,Spring 的cglib代理是用的是asm的这种方式
package cn.spring.test.utils;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import cn.spring.test.domain.Hello;
import javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import javassist.CtNewMethod;
import javassist.NotFoundException;
public class JavassistUtils {
/**
* Java字节码生成开源框架有Javassist,ASM Javassist已经加入了JBoss,JBoss用此实现了其动态AOP框架
* ASM操作级别是底层JVM的汇编指令级别,这要求ASM使用者要对class组织结构和JVM汇编指令有一定的了解,Spring 的cglib代理是用的是asm的这种方式
*
* @param args
* @throws NotFoundException
* @throws CannotCompileException
* @throws InstantiationException
* @throws IllegalAccessException
* @throws ClassNotFoundException
* @throws IOException
* @throws NoSuchMethodException
* @throws InvocationTargetException
*/
public static void main(String[] args) throws NotFoundException,
CannotCompileException, InstantiationException, IllegalAccessException, ClassNotFoundException, IOException, NoSuchMethodException, InvocationTargetException {
arroundMethod();
// assistMethod(); 只能修改一次
generatorClass();
}
static void arroundMethod() throws NotFoundException,
CannotCompileException, InstantiationException, IllegalAccessException, ClassNotFoundException {
//~加上报错,和类加载有关系,这里new的话会把Hello类加载,之后再加载的话就会报错
//Hello hell=new Hello();
//hell.sayHello();
//~
CtClass ctClass = ClassPool.getDefault().getCtClass("cn.spring.test.domain.Hello");
CtMethod ctMethod = ctClass.getDeclaredMethod("sayHello");
ctMethod.insertBefore("System.out.println(\"我是此方法执行前.....\");"); //相当于前置通知
ctMethod.insertAfter("System.out.println(\"我是此方法执行后.....\");"); //相当于后置通知
Class ch = ctClass.toClass(); //必须要有这句,相当于修改字节码文件内容
Hello h = (Hello) ch.newInstance();
h.sayHello();
Hello hel = new Hello();
hel.sayHello();
}
static void assistMethod() throws NotFoundException,
CannotCompileException, InstantiationException, IllegalAccessException, ClassNotFoundException {
//~加上报错,和类加载有关系,这里new的话会把Hello类加载,之后再加载的话就会报错
//Hello hell=new Hello();
//hell.sayHello();
//~
CtClass ctClass = ClassPool.getDefault().getCtClass("cn.spring.test.domain.Hello");
CtMethod ctMethod = ctClass.getDeclaredMethod("sayHello");
ctMethod.setBody("System.out.println(\"hi\");"); //修改其内容
Class ch = ctClass.toClass(); //必须要有这句,相当于修改字节码文件内容
Hello h = (Hello) ch.newInstance();
h.sayHello();
Hello hel = new Hello();
hel.sayHello();
}
static void generatorClass() throws CannotCompileException, IOException, ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InstantiationException, InvocationTargetException {
ClassPool pool = ClassPool.getDefault();
//创建Programmer类
CtClass cc = pool.makeClass("com.samples.Programmer");
//定义code方法
CtMethod method = CtNewMethod.make("public void code(){}", cc);
//插入方法代码
method.insertBefore("System.out.println(\"I'm a Programmer,Just Coding.....\");");
cc.addMethod(method);
Class ch = cc.toClass();
Method[] methodArr = OKhttpTest.class.getDeclaredMethods();
Method m = Class.forName("com.samples.Programmer").getDeclaredMethod("code", null);
m.invoke(ch.newInstance(), null);
//保存生成的字节码
// cc.writeFile("d://temp");
}
}