Sunday 3 May 2020

Javassist: Add an annotation to a run time generated class

Follow below steps to add annotation to a run time generated class.

Step 1: Define annotation.
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
public @interface Logger {
         String value();
}

Step 2: Get ClassPool Instance.
ClassPool classPool = ClassPool.getDefault();

Step 3: Create a class and get ClassFile and ConstPool references
CtClass ctClass = classPool.makeClass("com.sample.App.Test");
ClassFile classFile = ctClass.getClassFile();
ConstPool constPool = classFile.getConstPool();

Step 4: Define AnnotationAttribute that is to be added to the generated class.
AnnotationsAttribute annotationsAttribute = new AnnotationsAttribute(constPool,AnnotationsAttribute.visibleTag);
Annotation annotation = new Annotation("com.sample.app.annotations.Logger", constPool);
annotation.addMemberValue("value", new StringMemberValue("ERROR", constPool));
annotationsAttribute.addAnnotation(annotation);

Step 5: Add annotaton attribute the class file.
classFile.addAttribute(annotationsAttribute);

Find the below working application.

Logger.java
package com.sample.app.annotations;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD, ElementType.TYPE})
public @interface Logger {
 String value();
}

App.java
package com.sample.app;

import javassist.ClassPool;
import javassist.CtClass;
import javassist.bytecode.AnnotationsAttribute;
import javassist.bytecode.ClassFile;
import javassist.bytecode.ConstPool;
import javassist.bytecode.annotation.Annotation;
import javassist.bytecode.annotation.StringMemberValue;

public class App {

 public static void main(String args[]) throws Exception {
  ClassPool classPool = ClassPool.getDefault();

  // create a class and get ClassFile and ConstPool references
  CtClass ctClass = classPool.makeClass("com.sample.App.Test");
  ClassFile classFile = ctClass.getClassFile();
  ConstPool constPool = classFile.getConstPool();

  // create the annotation
  AnnotationsAttribute annotationsAttribute = new AnnotationsAttribute(constPool,
    AnnotationsAttribute.visibleTag);
  Annotation annotation = new Annotation("com.sample.app.annotations.Logger", constPool);
  annotation.addMemberValue("value", new StringMemberValue("ERROR", constPool));
  annotationsAttribute.addAnnotation(annotation);

  classFile.addAttribute(annotationsAttribute);

  ctClass.writeFile("/Users/Shared/javassist");
 }
}

Run App.java.

When you go to the directory /Users/Shared/javassist, you can see that Test.class file is created.
$tree /Users/Shared/javassist/
/Users/Shared/javassist/
└── com
    └── sample
        └── App
            └── Test.class

3 directories, 1 file

Open Test.class file in java de-compiler to see the source code.



You can confirm that @Logger annotation is added to Test class.
Previous                                                    Next                                                    Home

No comments:

Post a Comment