动态字节码技术Javassist

字节码技术可以动态改变某个类的结构(添加/删除/修改  新的属性/方法)

关于字节码的框架有javassist,asm,bcel等

引入依赖

<dependency>
     <groupId>javassist</groupId>
      <artifactId>javassist</artifactId>
      <version>3.12.1.GA</version>
</dependency>

生成字节码

//创建字节码文件
public class CreateClass {

    public static void main(String[] args) throws CannotCompileException, NotFoundException, IOException {
        ClassPool pool = ClassPool.getDefault();
        // 1.创建user类
        CtClass userClass = pool.makeClass("com.irish.entity.User");
        // 2.创建name 和age属性
        CtField nameField = CtField.make("private String name;", userClass);
        CtField ageField = CtField.make("private Integer age;", userClass);
        // 3.添加属性
        userClass.addField(nameField);
        userClass.addField(ageField);
        // 4.创建方法
        CtMethod nameMethod = CtMethod.make("public String getName() {return name;}", userClass);
        // 5.添加方法
        userClass.addMethod(nameMethod);
        // 6.添加构造函数
        CtConstructor ctConstructor = new CtConstructor(
                new CtClass[] { pool.get("java.lang.String"), pool.get("java.lang.Integer") }, userClass);

        ctConstructor.setBody("    { this.name = name; this.age = age; }");
        userClass.addConstructor(ctConstructor);

        // 生成class文件
        userClass.writeFile("F:/test");
        System.out.println("生成字节码,成功!");
    }

}

读取字节码后,对字节码新增方法,然后执行该方法

这里的User类要存在,UpdateClass 才可以读取出他的字节码后再修改

public class User {

    private String name;
    private Integer age;

}
//动态修改字节码文件
public class UpdateClass {

    @SuppressWarnings({ "rawtypes", "unchecked" })
    public static void main(String[] args) {
        try {
            ClassPool pool = ClassPool.getDefault();
            // 读取com.irish.User
            CtClass userClass = pool.get("com.irish.User");
            CtMethod method = new CtMethod(CtClass.voidType, "sum", new CtClass[] { CtClass.intType, CtClass.intType },
                    userClass);
            method.setBody("{System.out.println(\"sun:\" + ($1 + $2));}");
            // 添加方法
            userClass.addMethod(method);
            //将修改后的字节码写入到磁盘中,通过反编译工具,可以看到对类进行了修改
            userClass.writeFile("F:/test");
            // 动态执行方法
            Class clazz = userClass.toClass();
            Object newInstance = clazz.newInstance();
            Method sumMethod = clazz.getDeclaredMethod("sum", int.class, int.class);
            sumMethod.invoke(newInstance, 2, 5);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

猜你喜欢

转载自www.cnblogs.com/moris5013/p/11039997.html
今日推荐