Javassist

2020-03-15  本文已影响0人  百炼

Javassist是一款字节码编辑工具,同时也是一个动态类库,它可以直接检查、修改以及创建 Java类
在运行过程中创建类

以下例子就是创建一个动态类

package edu.cninfo.basic.day11;
import java.io.File;
import java.io.FileOutputStream;
import java.lang.reflect.Modifier;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtConstructor;
import javassist.CtField;
import javassist.CtMethod;
import javassist.CtNewMethod;
public class CompilerByJavassist {
    public static void main(String[] args) throws Exception {

        // ClassPool:CtClass对象的容器
        ClassPool pool = ClassPool.getDefault();

        // 通过ClassPool生成一个public新类Emp.java
        CtClass ctClass = pool.makeClass("com.study.javassist.Emp");

        // 添加属性
        // 首先添加属性private String ename
        CtField enameField = new CtField(pool.getCtClass("java.lang.String"),
                "ename", ctClass);
        enameField.setModifiers(Modifier.PRIVATE);
        ctClass.addField(enameField);

        // 其次添加熟悉privtae int eno
        CtField enoField = new CtField(pool.getCtClass("int"), "eno", ctClass);
        enoField.setModifiers(Modifier.PRIVATE);
        ctClass.addField(enoField);

        // 为属性ename和eno添加getXXX和setXXX方法
        ctClass.addMethod(CtNewMethod.getter("getEname", enameField));
        ctClass.addMethod(CtNewMethod.setter("setEname", enameField));
        ctClass.addMethod(CtNewMethod.getter("getEno", enoField));
        ctClass.addMethod(CtNewMethod.setter("setEno", enoField));

        // 添加构造函数
        CtConstructor ctConstructor = new CtConstructor(new CtClass[] {},
                ctClass);
        // 为构造函数设置函数体
        StringBuffer buffer = new StringBuffer();
        buffer.append("{\n").append("ename=\"yy\";\n").append("eno=001;\n}");
        ctConstructor.setBody(buffer.toString());
        // 把构造函数添加到新的类中
        ctClass.addConstructor(ctConstructor);

        // 添加自定义方法
        CtMethod ctMethod = new CtMethod(CtClass.voidType, "printInfo",
                new CtClass[] {}, ctClass);
        // 为自定义方法设置修饰符
        ctMethod.setModifiers(Modifier.PUBLIC);
        // 为自定义方法设置函数体
        StringBuffer buffer2 = new StringBuffer();
        buffer2.append("{\nSystem.out.println(\"begin!\");\n")
                .append("System.out.println(ename);\n")
                .append("System.out.println(eno);\n")
                .append("System.out.println(\"over!\");\n").append("}");
        ctMethod.setBody(buffer2.toString());
        ctClass.addMethod(ctMethod);

        //最好生成一个class
        Class<?> clazz = ctClass.toClass();
        Object obj = clazz.newInstance();
        //反射 执行方法
        obj.getClass().getMethod("printInfo", new Class[] {})
                .invoke(obj, new Object[] {});

        // 把生成的class文件写入文件
        byte[] byteArr = ctClass.toBytecode();
        FileOutputStream fos = new FileOutputStream(new File("D://Emp.class"));
        fos.write(byteArr);
        fos.close();
    }
}

Result:

运行代码控制台会打印如下内容,同时在D盘根目录生成一个Emp.class文件,反编译后的内容如下:

begin!
yy
1
over!
package com.study.javassist;

public class Emp {
    private String ename = "yy";
    private int eno = 1;

    public String getEname() {
        return this.ename;
    }

    public void setEname(String var1) {
        this.ename = var1;
    }

    public int getEno() {
        return this.eno;
    }

    public void setEno(int var1) {
        this.eno = var1;
    }

    public Emp() {
    }

    public void printInfo() {
        System.out.println("begin!");
        System.out.println(this.ename);
        System.out.println(this.eno);
        System.out.println("over!");
    }
}
上一篇下一篇

猜你喜欢

热点阅读