`

JDK6的新特性之六:插入式注解处理API(Pluggable Annotation Processing API)

 
阅读更多
插入式注解处理API(JSR 269)提供一套标准API来处理Annotations(JSR 175),实际上JSR 269不仅仅用来处理Annotation,我觉得更强大的功能是它建立了Java 语言本身的一个模型,它把method, package, constructor, type, variable, enum, annotation等Java语言元素映射为Types和Elements(两者有什么区别?), 从而将Java语言的语义映射成为对象, 我们可以在javax.lang.model包下面可以看到这些类. 所以我们可以利用JSR 269提供的API来构建一个功能丰富的元编程(metaprogramming)环境. JSR 269用Annotation Processor在编译期间而不是运行期间处理Annotation, Annotation Processor相当于编译器的一个插件,所以称为插入式注解处理.如果Annotation Processor处理Annotation时(执行process方法)产生了新的Java代码,编译器会再调用一次Annotation Processor,如果第二次处理还有新代码产生,就会接着调用Annotation Processor,直到没有新代码产生为止.每执行一次process()方法被称为一个"round",这样整个Annotation processing过程可以看作是一个round的序列. JSR 269主要被设计成为针对Tools或者容器的API. 举个例子,我们想建立一套基于Annotation的单元测试框架(如TestNG),在测试类里面用Annotation来标识测试期间需要执行的测试方法,如下所示:
 
@TestMethod
  public void testCheckName(){
        //do something here
  }
 
这时我们就可以用JSR 269提供的API来处理测试类,根据Annotation提取出需要执行的测试方法. 

另一个例子是如果我们出于某种原因需要自行开发一个符合Java EE 5.0的Application Server(当然不建议这样做),我们就必须处理Common Annotations(JSR 250),Web Services Metadata(JSR 181)等规范的Annotations,这时可以用JSR 269提供的API来处理这些Annotations. 在现在的开发工具里面,Eclipse 3.3承诺将支持JSR 269
 
下面我用代码演示如何来用JSR 269提供的API来处理Annotations和读取Java源文件的元数据(metadata)
 
 /**
  * Created by IntelliJ IDEA.
  * User: Chinajash
  * Date: Dec 31, 2006
  */
 @SupportedAnnotationTypes("PluggableAPT.ToBeTested")//可以用"*"表示支持所有Annotations
 @SupportedSourceVersion(SourceVersion.RELEASE_6)
 public class MyAnnotationProcessor extends AbstractProcessor {
     private void note(String msg) {
         processingEnv.getMessager().printMessage(Diagnostic.Kind.NOTE, msg);
     }
     public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
         //annotations的值是通过@SupportedAnnotationTypes声明的且目标源代码拥有的所有Annotations
         for(TypeElement te:annotations){
             note("annotation:"+te.toString());
         }
         Set<? extends Element> elements = roundEnv.getRootElements();//获取源代码的映射对象
         for(Element e:elements){
             //获取源代码对象的成员
             List<? extends Element> enclosedElems = e.getEnclosedElements();
             //留下方法成员,过滤掉其他成员
             List<? extends ExecutableElement> ees = ElementFilter.methodsIn(enclosedElems);
             for(ExecutableElement ee:ees){
                 note("--ExecutableElement name is "+ee.getSimpleName());
                 List<? extends AnnotationMirror> as = ee.getAnnotationMirrors();//获取方法的Annotations
                 note("--as="+as); 
                for(AnnotationMirror am:as){
                     //获取Annotation的值
                     Map<? extends ExecutableElement, ? extends AnnotationValue> map= am.getElementValues();
                     Set<? extends ExecutableElement> ks = map.keySet();
                     for(ExecutableElement k:ks){//打印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();
 }
 
编译以上代码,然后再创建下面的Testing对象,不要编译Testing对象,我在后面会编译它
 
public class Testing{    
    @ToBeTested(group="A")
     public void m1(){
     }
     @ToBeTested(group="B",owner="QQ")
     public void m2(){
     }    
    @PostConstruct//Common Annotation里面的一个Annotation
     public void m3(){
     }    
}
 
下面我用以下命令编译Testing对象
 
javac -XprintRounds -processor PluggableAPT.MyAnnotationProcessor Testing.java
 
-XprintRounds表示打印round的次数,运行上面命令后在控制台会看到如下输出:
 
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: ")
 Note: ----m1.group=A
 Note: --ExecutableElement name is m2
 Note: ", 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
 
本来想用JDK6.0的Compiler API来执行上面编译命令,可是好像现在Compiler API还不支持-processor参数,运行时总报以下错误
 
Exception in thread "main" java.lang.IllegalArgumentException: invalid flag: -processor PluggableAPT.MyAnnotationProcessor
 
调用Compiler API的代码是这样的
 
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();
 
不知道这是不是Compiler API的一个bug.

 

分享到:
评论

相关推荐

    JDK1.6的九大新特性

    六:插入式注解处理API(Pluggable Annotation Processing API) 五:轻量级Http Server API 四:使用Compiler API 三:理解StAX 二:使用JAXB2来实现对象与XML之间的映射 一:Desktop类和SystemTray类

    JDK1.6新特性与实战例子

    JDK6的新特性之一:Desktop类和SystemTray类 JDK6的新特性之二:使用JAXB2来实现对象与XML之间的映射 JDK6的新特性之三:理解StAX StAX(JSR 173)是JDK6.0中除了DOM和SAX之外的又一种处理XML文档的API JDK6的新特性...

    JDK+6.0+ZH+API.chm.zip

    JDK6的新特性之六_插入式注解处理API JDK6的新特性之九_CommonAnnotations JDK6的新特性之十_Web服务元数据 JDK6的新特性之十一_更简单强大的JAX-WS JDK6的新特性之十三_JTable的排序和过滤 JDK6的新特性之...

    JDK 6.2.3文文档.rar

    插入式注解处理API(Pluggable Annotation Processing API) 用Console开发控制台程序 对脚本语言的支持(如:ruby,groovy,javascript) Common Annotations ———————————————— 版权声明:本文为...

    javax.annotation-api-1.3.2

    JDK9及以上版本没有javax.annotation-api-***.jar包 ,无法使用注解:@Resource JDK新特性,高版本JDK没有自带的javax(java扩展包)了。或者是使用的JDK不完整。 下载javax.annotation.jar包,导入到lib文件夹下,...

    计算机后端-Java-Java核心基础-第23章 枚举类与注解 16. jdk8新特性:可重复注解.avi

    计算机后端-Java-Java核心基础-第23章 枚举类与注解 16. jdk8新特性:可重复注解.avi

    JDK1.8 API 中文文档以及新特性pdf 讲解 带代码示例

    其中代码示例 jdk8的特性使用pdf 其中JDK1.8 API 中文文档以及新特性pdf 讲解 带代码示例 JDK1.8 API 中文文档以及新特性pdf 讲解 带代码示例

    jdk1.6.0_45

    jdk1.6新特性 1.Desktop类和SystemTray类 2.使用JAXB2来实现对象与XML之间的映射 ...6.插入式注解处理API(Pluggable Annotation Processing API) 7.用Console开发控制台程序 8.对脚本语言的支持 9.Common Annotations

    jdk1.8新特性.doc

    本文主要介绍了JDK1.8版本中的一些新特性,仅供参考。 jdk1.8新特性知识点: 1、Lambda表达式 2、函数式接口 3、方法引用和构造器调用 4、Stream API 5、接口中的默认方法和静态方法 6、新时间日期API

    JAVA6新特性介绍.zip

    jdk1.6新特性 1.Desktop类和SystemTray类 2.使用JAXB2来实现对象与XML之间的映射 ...6.插入式注解处理API(Pluggable Annotation Processing API) 7.用Console开发控制台程序 8.对脚本语言的支持 9.Common Annotations

    jdk1.8 新特性.docx

    jdk1.8新特性知识点: Lambda表达式 函数式接口 *方法引用和构造器调用 Stream API 接口中的默认方法和静态方法 新时间日期API

    Annotation(注解)详细教程,jdk新特性

    Annotation 注解 新特性 jdk1.6 jdk1.5 很详细的学习资料

    Java 7.0 JDK 7 API CHM part02

    Java 7.0 JDK 7 API CHM part02 本资源有五个压缩包,请全部下载后再解压 下载地址如下: Java 7.0 JDK 7 API CHM part05: http://download.csdn.net/source/3487478 Java 7.0 JDK 7 API CHM part04: ...

    Java 7.0 JDK 7 API CHM part03

    Java 7.0 JDK 7 API CHM part03 本资源有五个压缩包,请全部下载后再解压 下载地址如下: Java 7.0 JDK 7 API CHM part05: http://download.csdn.net/source/3487478 Java 7.0 JDK 7 API CHM part04: ...

    Java 7.0 JDK 7 API CHM part05

    Java 7.0 JDK 7 API CHM part05 本资源有五个压缩包,请全部下载后再解压 下载地址如下: Java 7.0 JDK 7 API CHM part05: http://download.csdn.net/source/3487478 Java 7.0 JDK 7 API CHM part04: ...

    Java 7.0 JDK 7 API CHM part01

    Java 7.0 JDK 7 API CHM part01 本资源有五个压缩包,请全部下载后再解压 下载地址如下: Java 7.0 JDK 7 API CHM part05: http://download.csdn.net/source/3487478 Java 7.0 JDK 7 API CHM part04: ...

    Java 7.0 JDK 7 API CHM part04

    Java 7.0 JDK 7 API CHM part04 本资源有五个压缩包,请全部下载后再解压 下载地址如下: Java 7.0 JDK 7 API CHM part05: http://download.csdn.net/source/3487478 Java 7.0 JDK 7 API CHM part04: ...

    511.509.JAVA基础教程_枚举类与注解-jdk8新特性:类型注解(511).rar

    511.509.JAVA基础教程_枚举类与注解-jdk8新特性:类型注解(511).rar

    计算机后端-Java-Java核心基础-第23章 枚举类与注解 17. jdk8新特性:类型注解.avi

    计算机后端-Java-Java核心基础-第23章 枚举类与注解 17. jdk8新特性:类型注解.avi

    JDK-API-1-6-zzh-CN帮助文档中文版

    Java SE 6包括许多新的特性和改进,包括JDBC 4.0 API,Java Compiler API,Pluggable Annotation Processing API和新的XML和Web服务API等。此外,Java SE 6还包括对桌面应用程序的增强支持,如Swing,Java2D和Java ...

Global site tag (gtag.js) - Google Analytics