Compile Time Annotation Parsing
Annotation which is being primarily used for metadata purposes in Code needs to be parsed to imply the purpose they are intended for.
Annotation Parsing is basically done at runtime with Reflections api. This is the usual approach which we generally folow.
Apart from the above mentioned fact annotation parsing can also be done at Compile Time and in this post I am going to
throw some light into that.
Compile Time annotation Parsing follows the SPI (Service Provider Interface) architecture.
To achieve this:
I have declared a Custom annotation as follows:
The main thing to look aout for in the above code is the Retention Policy, which is Source, which is normally Runtime
when we use annotation parsing at runtime with Reflections.
Now we define the annotation parsing engine as follows (Please note no additional jars are required):
Now, this parsing engine should be configured in such a way to make it understand which annotations it would
look out for (or which options it needs to be recognized) and this is being done with the help of @SupportedAnnotationTypes annotation ,
where we have listed down our custom annotation.
We have also used @SupportedSourceVersion annotation to imply the Java Version to be used for.
Now, the engine class extends AbstractProcessor abstract class which contains all the predefined contracts.
The process() method is the only abstract method in the class AbstractProcessor which is being implemented out here.
Now, in the process() method we are fetching all the elements annotated with our custom annotation and doing all other required processing.
Now, this Engine class is declared in a file named javax.annotation.processing.Processor within META-INF/services
directory (In accordance with the SPI architecture).
The content of the file is: com.subha.annotation.custom.CompileTimeParsingEngine i.e. fully qualified
class name of out annotation engine.
Now we build a jar with the following Structure:
CompileAnn.jar ---> com/subha/annotation/custom/CompileTimeParsing.class
com/subha/annotation/custom/CompileTimeParsingEngine.class
META-INF/MANIFEST.MF
META-INF/services/javax.annotation.processing.Processor
Now to test our Custom annotation along with the annotation parsing engine, we have declared as follows:
Now we run the following command from the command line as we can view the required output.
javac -cp F:\My_Work\New_Spring_Workspaces\SPIAndCDI\jar\CompileAnn.jar
F:\My_Work\New_Spring_Workspaces\Test\src\com\subha\test\CompileTimeAnnParsingTest.java
The output is:
I am Here
Note: Methods found in CompileTimeAnnParsingTest:
hashCode
equals
toString
annotationType
isProxyClass
getProxyClass
getInvocationHandler
newProxyInstance
wait
wait
wait
getClass
notify
notifyAll
Annotation Parsing is basically done at runtime with Reflections api. This is the usual approach which we generally folow.
Apart from the above mentioned fact annotation parsing can also be done at Compile Time and in this post I am going to
throw some light into that.
Compile Time annotation Parsing follows the SPI (Service Provider Interface) architecture.
To achieve this:
I have declared a Custom annotation as follows:
import java.lang.annotation.Inherited; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @Inherited @Retention(RetentionPolicy.SOURCE) public @interface CompileTimeParsing { }
The main thing to look aout for in the above code is the Retention Policy, which is Source, which is normally Runtime
when we use annotation parsing at runtime with Reflections.
Now we define the annotation parsing engine as follows (Please note no additional jars are required):
import java.lang.reflect.Method; import java.util.Set; import javax.annotation.processing.AbstractProcessor; import javax.annotation.processing.RoundEnvironment; import javax.annotation.processing.SupportedAnnotationTypes; import javax.annotation.processing.SupportedSourceVersion; import javax.lang.model.SourceVersion; import javax.lang.model.element.TypeElement; import javax.lang.model.element.Element; import javax.tools.Diagnostic; @SupportedAnnotationTypes("com.subha.annotation.custom.CompileTimeParsing") @SupportedSourceVersion(SourceVersion.RELEASE_6) public class CompileTimeParsingEngine extends AbstractProcessor{ @Override public boolean process(Set annotations, RoundEnvironment roundEnv) { // TODO Auto-generated method stub StringBuilder message = new StringBuilder(); for (Element elem : roundEnv.getElementsAnnotatedWith(CompileTimeParsing.class)) { CompileTimeParsing implementation = elem.getAnnotation(CompileTimeParsing.class); System.out.println(" I am Here "); message.append("Methods found in " + elem.getSimpleName().toString() + ":\n"); for (Method method : implementation.getClass().getMethods()) { message.append(method.getName() + "\n"); } processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, message.toString()); } return false; // allow others to process this annotation type } }
Now, this parsing engine should be configured in such a way to make it understand which annotations it would
look out for (or which options it needs to be recognized) and this is being done with the help of @SupportedAnnotationTypes annotation ,
where we have listed down our custom annotation.
We have also used @SupportedSourceVersion annotation to imply the Java Version to be used for.
Now, the engine class extends AbstractProcessor abstract class which contains all the predefined contracts.
The process() method is the only abstract method in the class AbstractProcessor which is being implemented out here.
Now, in the process() method we are fetching all the elements annotated with our custom annotation and doing all other required processing.
Now, this Engine class is declared in a file named javax.annotation.processing.Processor within META-INF/services
directory (In accordance with the SPI architecture).
The content of the file is: com.subha.annotation.custom.CompileTimeParsingEngine i.e. fully qualified
class name of out annotation engine.
Now we build a jar with the following Structure:
CompileAnn.jar ---> com/subha/annotation/custom/CompileTimeParsing.class
com/subha/annotation/custom/CompileTimeParsingEngine.class
META-INF/MANIFEST.MF
META-INF/services/javax.annotation.processing.Processor
Now to test our Custom annotation along with the annotation parsing engine, we have declared as follows:
import com.subha.annotation.custom.CompileTimeParsing; @CompileTimeParsing public class CompileTimeAnnParsingTest { }
Now we run the following command from the command line as we can view the required output.
javac -cp F:\My_Work\New_Spring_Workspaces\SPIAndCDI\jar\CompileAnn.jar
F:\My_Work\New_Spring_Workspaces\Test\src\com\subha\test\CompileTimeAnnParsingTest.java
The output is:
I am Here
Note: Methods found in CompileTimeAnnParsingTest:
hashCode
equals
toString
annotationType
isProxyClass
getProxyClass
getInvocationHandler
newProxyInstance
wait
wait
wait
getClass
notify
notifyAll
Comments
Post a Comment