博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java get set6_JDK6的新特性(转)
阅读量:6409 次
发布时间:2019-06-23

本文共 4384 字,大约阅读时间需要 14 分钟。

JDK6的新特性之六:插入式注解处理API

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: --as=@PluggableAPT.ToBeTested(group="A")

Note: ----m1.group=A

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

本来想用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 options = new HashSet();

options.add("-processor PluggableAPT.MyAnnotationProcessor");

compiler.getTask(null, fileManager, null, options, null, sourcefiles).call();

不知道这是不是Compiler API的一个bug.

转载地址:http://zmwra.baihongyu.com/

你可能感兴趣的文章
winform自定义控件
查看>>
C#编码好习惯
查看>>
避其锋芒,侧翼出击。——司马亮创业回忆录(一)
查看>>
scope
查看>>
一起谈.NET技术,晚绑定场景下对象属性赋值和取值可以不需要PropertyInfo
查看>>
一起谈.NET技术,.Net Framework源代码中的模式之Prototype(原型模式)
查看>>
[shell 命令] find 查找文件
查看>>
windows下启动mysql服务的命令行启动和手动启动方法
查看>>
VTK三维点集轮廓凸包提取
查看>>
【概率论与数理统计】小结9-3 - 区间估计
查看>>
Golang性能调优入门
查看>>
sqlloader外部表
查看>>
golang笔记——数组与切片
查看>>
屏蔽可忽略的js脚本错误
查看>>
【Vue】vue.js常用指令
查看>>
NFS学习
查看>>
MySql常用命令总结
查看>>
又一年...
查看>>
文件上传框的美化+预览+ajax
查看>>
Linux VFS
查看>>