Friday, December 20, 2013

Annotation parser in Java

Java SE 5 introduced Annotation processing API; which further got extended in Java 6 and in Java 7. Through this API, you can find annotations in your code base and then work with them. 

I have discussed the basics of Annotation in the previous post, link. In this post, I will be focusing on processing annotations put in a class file. 



Annotation Processor

This post will be diving deeper to understand how to process Annotations in a class file. If there is no logic/tool to process/parse annotations embedded in source code then annotations will look more like comments. Java provides support API to create these tools through reflection technique
Before finally looking into Annotation processors; let's see one sample annotation and its use. Below is a definition of an Annotation. Note, the meta-annotation put in below Annotation (meta-annotations have been discussed in the previous post). InvocationAnnotation will be used to specify how many times a method needs to run. 

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)
public @interface InvocationAnnotation {
 int numberOfTimesToInvoke() default 1;
}


Now let's take a class where above annotation, InvocationAnnotation will be used. 


public class AnnotationUsage {
 @InvocationAnnotation(numberOfTimesToInvoke = 3)
 public void method1() {
  System.out.println(" method1 invocation ....3 times..");
 }

 @InvocationAnnotation
 public void method2() {
  System.out.println(" method2 invocation...1 time");
 }
}


Now let's turn to the real business of extracting information from above class and the performing task as expected.

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class ProcessAnnotationUsage {
 public static void main(String[] args) {
  AnnotationUsage at = new AnnotationUsage();
  Method[] methods = at.getClass().getMethods();

  for (Method m : methods) {

   InvocationAnnotation ia = m
     .getAnnotation(InvocationAnnotation.class);

   if (ia != null) {
    int count = ia.numberOfTimesToInvoke();

    for (int i = 0; i < count; i++) {
     try {
      m.invoke(at, null);
     } catch (IllegalAccessException 
      | IllegalArgumentException
      | InvocationTargetException e) {
      e.printStackTrace();
     }
    }
   }
  }
 }
}

Output :

method1 invocation ....3 times..

 method1 invocation ....3 times..

 method1 invocation ....3 times..

 method2 invocation...1 time


So above annotation processor reads annotation embedded in method through reflection. Then,  finds out how many times the method needs to be invoked and then finally does that using for loop. The output confirms the same. 

Java 5 also introduced an Annotation Processing Tool (APT) called as apt. And in JDK 6, apt was made part of the compiler.

---
do post your comments/questions below !!!

No comments:

Post a Comment