New feature 6 of JDK 6: plug-in Annotation processing API (Pluggable annotation processing API)
The plug-in Annotation processing API (JSR 269) provides a set of standard APIs to process annotations (JSR 175). In fact, JSR 269 is not only used to process annotation, I think the more powerful feature is that it builds a model of the Java language itself. It sets method, package, constructor, type, variable, Enum, annotation and other Java language elements are mapped to types and elements (what is the difference between the two ?), To map the semantics of the Java language to an object, we can. lang. you can see these classes under the model package. therefore, we can use the APIS provided by JSR 269 to build a feature-rich metaprogramming environment. JSR 269 uses annotation processor to process annotation during compilation rather than during runtime. annotation processor is equivalent to a plug-in of the compiler, so it is called plug-in Annotation processing. if annotation processor generates a new Java code when processing annotation (the process method is executed), the compiler will call annotation processor again. If new code is generated during the second processing, the annotation processor will be called until no new code is generated. each execution of the process () method is called a "round", so that the entire annotation processing process can be considered as a round sequence. JSR 269 is mainly designed as an API for tools or containers. for example, we want to establish an annotation-based unit test framework (such as testng). In the test class, annotation is used to identify the testing method to be executed during the test, as shown below:
@ Testmethod
Public void testcheckname (){
// Do something here
}
In this case, we can use the APIS provided by JSR 269 to process the test class and extract the testing method to be executed based on annotation.
Another example is that if we need to develop an application server that complies with Java EE 5.0 for some reason (this is not recommended, of course), we must handle common annotations (JSR 250 ), for standardized annotations such as Web services metadata (JSR 181), Apis provided by JSR 269 can be used to process these annotations. in the current development tools, eclipse 3.3 promises to support JSR 269
The following code demonstrates how to use APIs provided by JSR 269 to process annotations and read metadata (metadata) of Java source files)
/**
* Created by intellij idea.
* User: chinajash
* Date: Dec 31,200 6
*/
@ Supportedannotationtypes ("pluggableapt. tobetested") // you can use "*" to support all annotations.
@ Supportedsourceversion (sourceversion. release_6)
Public class myannotationprocessor extends actprocessor {
Private void note (string MSG ){
Processingenv. getmessager (). printmessage (diagnostic. Kind. Note, MSG );
}
Public Boolean Process (set <? Extends typeelement> annotations, roundenvironment roundenv ){
// The value of annotations is all annotations declared by @ supportedannotationtypes and owned by the target source code
For (typeelement te: Annotations ){
Note ("annotation:" + Te. tostring ());
}
Set <? Extends element> elements = roundenv. getrootelements (); // gets the source code ing object.
For (Element E: Elements ){
// Obtain the source code object Member
List <? Extends element> enclosedelems = E. getenclosedelements ();
// Leave the method member and filter out other members.
List <? Extends executableelement> ees = elementfilter. methodsin (enclosedelems );
For (executableelement EE: EES ){
Note ("-- executableelement name is" + ee. getsimplename ());
List <? Extends annotationmirror> As = ee. getannotationmirrors (); // obtain annotations of methods
Note ("-- as =" + );
For (annotationmirror AM: ){
// Obtain the annotation Value
Map <? Extends executableelement ,? Extends annotationvalue> map = aM. getelementvalues ();
Set <? Extends executableelement> Ks = map. keyset ();
For (executableelement K: Ks) {// print each value of Annotation
Annotationvalue AV = map. Get (k );
Note ("----" + ee. getsimplename () + "." + K. getsimplename () + "=" + AV. getvalue ());
}
}
}
}
Return false;
}
}
@ Retention (retentionpolicy. runtime)
@ Target (elementtype. Method)
@ Interface tobetested {
String owner () Default "chinajash ";
String group ();
}
Compile the above code, and then create the following testing object. do not compile the testing object. I will compile it later.
Public class testing {
@ Tobetested (group = "")
Public void M1 (){
}
@ Tobetested (group = "B", owner = "QQ ")
Public void m2 (){
}
@ Postconstruct // an annotation in the common Annotation
Public void m3 (){
}
}
The following command is used to compile the testing object:
Javac-xprintrounds-processor pluggableapt. myannotationprocessor testing. Java
-Xprintrounds indicates the number of round printing times. After running the preceding command, the following output is displayed on the console:
Round 1:
Input files: {pluggableapt. Testing}
Annotations: [pluggableapt. tobetested, javax. annotation. postconstruct]
Last round: false
Note: annotation: pluggableapt. tobetested
Note: -- executableelement name is M1
Note: -- As = @ pluggableapt. tobetested (group = "")
Note: ---- m1.group =
Note: -- executableelement name is m2
Note: -- As = @ pluggableapt. tobetested (group = "B", owner = "QQ ")
Note: ---- m2.group = B
Note: ---- m2.owner = QQ
Note: -- executableelement name is m3
Note: -- As = @ javax. annotation. postconstruct
Round 2:
Input files :{}
Annotations: []
Last round: True
I originally wanted to use the compiler API of jdk6.0 to execute the above compilation command. However, it seems that the compiler API does not support the-processor parameter yet, and the following error is always reported during running.
Exception in thread "Main" Java. Lang. illegalargumentexception: Invalid flag:-processor pluggableapt. myannotationprocessor
The code for calling the compiler API is as follows:
Javacompiler compiler = toolprovider. getsystemjavacompiler ();
Standardjavafilemanager filemanager = compiler. getstandardfilemanager (null, null, null );
Iterable <? Extends javafileobject> sourcefiles = filemanager. getjavafileobjects ("testing. Java ");
Set <string> Options = new hashset <string> ();
Options. Add ("-processor pluggableapt. myannotationprocessor ");
Compiler. gettask (null, filemanager, null, options, null, sourcefiles). Call ();
I don't know if this is a compiler API bug.