插入式注解处理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.
分享到:
相关推荐
六:插入式注解处理API(Pluggable Annotation Processing API) 五:轻量级Http Server API 四:使用Compiler API 三:理解StAX 二:使用JAXB2来实现对象与XML之间的映射 一:Desktop类和SystemTray类
JDK6的新特性之六_插入式注解处理API JDK6的新特性之九_CommonAnnotations JDK6的新特性之十_Web服务元数据 JDK6的新特性之十一_更简单强大的JAX-WS JDK6的新特性之十三_JTable的排序和过滤 JDK6的新特性之...
插入式注解处理API(Pluggable Annotation Processing API) 用Console开发控制台程序 对脚本语言的支持(如:ruby,groovy,javascript) Common Annotations ———————————————— 版权声明:本文为...
JDK9及以上版本没有javax.annotation-api-***.jar包 ,无法使用注解:@Resource JDK新特性,高版本JDK没有自带的javax(java扩展包)了。或者是使用的JDK不完整。 下载javax.annotation.jar包,导入到lib文件夹下,...
Java Development Kit (JDK) 6是Java编程语言的一个重要版本,它在2006年发布,带来了许多新特性和改进,提升了开发者的效率和应用程序的性能。在这个版本中,Oracle(当时还是Sun Microsystems)引入了对JavaScript...
新时间日期API是JDK8的新特性之一,提供了对日期和时间的操作和处理。例如: public static void main(String[] args) { LocalDate date = LocalDate.now(); System.out.println("当前日期:" + date); } JDK8新...
7. **插入式注解处理API (Pluggable Annotation Processing API)**: 这个API允许开发者创建自定义的注解处理器,可以在编译期间自动执行某些任务,比如代码生成或验证。 8. **Console开发控制台程序**: JDK 1.6增强...
计算机后端-Java-Java核心基础-第23章 枚举类与注解 16. jdk8新特性:可重复注解.avi
Lambda表达式是JDK1.8最显著的新特性之一,它简化了函数式编程,使得可以以更简洁的方式编写匿名函数。Lambda表达式可以替代只包含单个抽象方法的接口的实现,例如`Runnable`和`Comparator`。使用lambda,你可以这样...
jdk1.6新特性 1.Desktop类和SystemTray类 2.使用JAXB2来实现对象与XML之间的映射 ...6.插入式注解处理API(Pluggable Annotation Processing API) 7.用Console开发控制台程序 8.对脚本语言的支持 9.Common Annotations
jdk1.6新特性 1.Desktop类和SystemTray类 2.使用JAXB2来实现对象与XML之间的映射 ...6.插入式注解处理API(Pluggable Annotation Processing API) 7.用Console开发控制台程序 8.对脚本语言的支持 9.Common Annotations
Annotation(注解)是Java编程语言的一个重要特性,自JDK 1.5引入以来,逐渐成为编写可维护和可扩展代码的关键工具。注解提供了一种方式,使得程序员可以在代码中添加元数据(metadata),这些数据不直接影响代码...
《深入解析JDK6 API中文版》 JDK(Java Development Kit)是Oracle公司发布的用于开发Java应用程序的软件包,其中包含了Java运行环境、编译器、类库以及各种工具。JDK6作为Java发展历程中的一个重要版本,为开发者...
6. **JDK7新特性<六> 监听文件系统的更改** 这个特性允许程序注册监听文件或目录的改变,当文件系统发生变动时,可以立即响应,增强了实时性和效率,特别是在文件监控应用中非常有用。 7. **JDK7新特性<七> 遍历...
JDK8引入了新的注解特性,增强了注解的可读性和实用性,使得开发者能更好地利用注解来简化代码和提高效率。本篇文章将深入探讨JDK8中的注解应用。 一、元注解 元注解是用于定义其他注解的注解。JDK8中包含以下元...
**JDK6的新特性** Java Development Kit (JDK) 6是Java编程语言的一个重要版本,它在2006年发布,引入了一系列创新特性和改进,极大地提升了开发人员的效率和应用程序的性能。以下是对JDK6主要新特性的详细解析: ...
2. **Stream API**:新的Stream API允许开发者对集合进行声明式处理,提供了更高效、更简洁的代码来执行聚合操作,如过滤、映射、排序和收集。 3. **默认方法**:在接口中可以定义具有实现的方法,这允许接口在不...
3. 文件系统API(NIO.2):JDK 1.7引入了新的文件系统API,允许更灵活、更安全地操作文件和目录,包括异步I/O和文件属性查询。 4. try-with-resources:此语法糖使得资源管理更加简洁,自动关闭在try块中打开的流和...