javaassist對class的字節碼的動態修改

javaassist的maven依賴:

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

Person類:

public class Person {
    private String name;
    private int age;
    private boolean sex;
    private String address;
}

動態添加方法:

ClassPool classPool = ClassPool.getDefault();

        CtClass ctClass = classPool.makeClass("application.Person");

        CtMethod ctMethod = CtNewMethod.make("public void sayHello(String name){\n" +
                "        System.out.println(\"得到的是一個名稱\" + name);\n" +
                "    }",ctClass);

        ctClass.addMethod(ctMethod);

        Class aClass = ctClass.toClass();

        Object object = aClass.newInstance();
        Method sayHello = aClass.getDeclaredMethod("sayHello", String.class);

        sayHello.invoke(object,"王天龍");

動態添加屬性:

ClassPool classPool = ClassPool.getDefault();

        CtClass ctClass = classPool.get("application.Person");

        CtField ctField = CtField.make("private String phone;", ctClass);
        ctClass.addField(ctField);
        Class aClass = ctClass.toClass();
        Field[] declaredFields = aClass.getDeclaredFields();

        for (Field field : declaredFields){
            System.out.println(field);
        }

運行結果:

private java.lang.String application.Person.name
private int application.Person.age
private boolean application.Person.sex
private java.lang.String application.Person.address
private java.lang.String application.Person.phone

動態添加構造函數:

ClassPool classPool = ClassPool.getDefault();

        CtClass ctClass = classPool.get("application.Person");
        CtConstructor ctConstructor = CtNewConstructor.make("public Person(String name, int age, boolean sex, String address) {\n" +
                "        this.name = name;\n" +
                "        this.age = age;\n" +
                "        this.sex = sex;\n" +
                "        this.address = address;\n" +
                "    }", ctClass);
        ctClass.addConstructor(ctConstructor);

        Class aClass = ctClass.toClass();
        Constructor[] declaredConstructors = aClass.getDeclaredConstructors();
        for (Constructor constructor : declaredConstructors){
            System.out.println(constructor);
        }

運行結果:

public application.Person()
public application.Person(java.lang.String,int,boolean,java.lang.String)

動態添加註解:

ClassPool classPool = ClassPool.getDefault();

        CtClass ctClass = classPool.get("application.Person");
        ClassFile classFile = ctClass.getClassFile();
        ConstPool constPool = classFile.getConstPool();

        AnnotationsAttribute annotationsAttribute = new AnnotationsAttribute(constPool, AnnotationsAttribute.visibleTag);

        Annotation annotation = new Annotation("org.springframework.stereotype.Service",constPool);

        annotationsAttribute.addAnnotation(annotation);
        classFile.addAttribute(annotationsAttribute);

        Class aClass = ctClass.toClass();
        java.lang.annotation.Annotation[] declaredAnnotations = aClass.getDeclaredAnnotations();
        for (java.lang.annotation.Annotation anno : declaredAnnotations){
            System.out.println(anno);
        }

運行結果:

@org.springframework.stereotype.Service(value=)

動態插入代碼塊:

ClassPool classPool = ClassPool.getDefault();

        CtClass ctClass = classPool.get("application.Person");

        CtMethod sayHello = ctClass.getDeclaredMethod("sayHello", new CtClass[]{
                classPool.get(String.class.getCanonicalName())
        });
        sayHello.insertBefore("int num1 = 1;\n" +
                "        int num2 = 2;\n" +
                "        System.out.println(num1 + num2);");
        sayHello.insertAt(22,"System.out.println(\"插入的代碼\");");
        sayHello.insertAfter("int num1 = 1;\n" +
                "        int num2 = 2;\n" +
                "        System.out.println(num1 + num2);");
        Class aClass = ctClass.toClass();
        Object object = aClass.newInstance();
        Method method = aClass.getDeclaredMethod("sayHello", String.class);

        method.invoke(object,"王天龍");

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章