Java注解学习笔记(三)编译时注解

编译时注解(RetentionPolicy.CLASS)

概念定义

       说到编译时注解(RetentionPolicy.CLASS) 都要和 注解处理器(Annotation Processor) 扯上关系,因为这里是真正体现编译时注解价值的地方。需要注意的一点是,运行时注解(RetentionPolicy.RUNTIME)和源码注解(RetentionPolicy.SOURCE)也可以在注解处理器进行处理,不同的注解有各自的生命周期,根据你实际使用来确定。

注解处理器(Annotation Processor)

       首先来了解下什么是注解处理器,注解处理器是javac的一个工具,它用来在编译时扫描和处理注解。你可以自定义注解,并注册到相应的注解处理器,由注解处理器来处理你的注解。一个注解的注解处理器,以Java代码(或者编译过的字节码)作为输入,生成文件(通常是.java文件)作为输出。这些生成的Java代码是在生成的.java文件中,所以你不能修改已经存在的Java类,例如向已有的类中添加方法。这些生成的Java文件,会同其他普通的手动编写的Java源代码一样被javac编译。
       先来定义要使用的注解,这里建一个Java库来专门放注解,库名为:annotations。注解库指定JDK版本为1.7,如何指定往下看。自定义注解如下:

/**
 * 编译时注解
 */
@Retention(RetentionPolicy.CLASS)
@Target(ElementType.TYPE)
public @interface MyAnnotation {
    String value();
}

       这里定义一个注解处理器 MyProcessor,每一个处理器都是继承于 AbstractProcessor,并要求必须复写 process() 方法,通常我们使用会去复写以下4个方法:

/**
 * 每一个注解处理器类都必须有一个空的构造函数,默认不写就行;
 */
public class MyProcessor extends AbstractProcessor {
 
    /**
     * init()方法会被注解处理工具调用,并输入ProcessingEnviroment参数。
     * ProcessingEnviroment提供很多有用的工具类Elements, Types 和 Filer
     * @param processingEnv 提供给 processor 用来访问工具框架的环境
     */
    @Override
    public synchronized void init(ProcessingEnvironment processingEnv) {
        super.init(processingEnv);
    }
 
    /**
     * 这相当于每个处理器的主函数main(),你在这里写你的扫描、评估和处理注解的代码,以及生成Java文件。
     * 输入参数RoundEnviroment,可以让你查询出包含特定注解的被注解元素
     * @param annotations   请求处理的注解类型
     * @param roundEnv  有关当前和以前的信息环境
     * @return  如果返回 true,则这些注解已声明并且不要求后续 Processor 处理它们;
     *          如果返回 false,则这些注解未声明并且可能要求后续 Processor 处理它们
     */
    @Override
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
        return false;
    }
 
    /**
     * 这里必须指定,这个注解处理器是注册给哪个注解的。注意,它的返回值是一个字符串的集合,包含本处理器想要处理的注解类型的合法全称
     * @return  注解器所支持的注解类型集合,如果没有这样的类型,则返回一个空集合
     */
    @Override
    public Set<String> getSupportedAnnotationTypes() {
        Set<String> annotataions = new LinkedHashSet<String>();
        annotataions.add(MyAnnotation.class.getCanonicalName());
        return annotataions;
    }
 
    /**
     * 指定使用的Java版本,通常这里返回SourceVersion.latestSupported(),默认返回SourceVersion.RELEASE_6
     * @return  使用的Java版本
     */
    @Override
    public SourceVersion getSupportedSourceVersion() {
        return SourceVersion.latestSupported();
    }
}

       上面注释说的挺清楚了,我们需要处理的工作在 process() 方法中进行,等下给出例子。对于 getSupportedAnnotationTypes() 方法标明了这个注解处理器要处理哪些注解,返回的是一个Set 值,说明一个注解处理器可以处理多个注解。除了在这个方法中指定要处理的注解外,还可以通过注解的方式来指定(SourceVersion也一样):

@SupportedSourceVersion(SourceVersion.RELEASE_8)
@SupportedAnnotationTypes("com.example.annotation.cls.MyAnnotation")
public class MyProcessor extends AbstractProcessor {
    // ...
}
// 建议使用重载 getSupportedAnnotationTypes() 和 getSupportedSourceVersion()方法代替 @SupportedAnnotationTypes 和 @SupportedSourceVersion
// 现在来添加对注解的处理,简单的输出一些信息即可,代码如下:
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
    // roundEnv.getElementsAnnotatedWith()返回使用给定注解类型的元素
    for (Element element : roundEnv.getElementsAnnotatedWith(MyAnnotation.class)) {
        System.out.println("------------------------------");
        // 判断元素的类型为Class
        if (element.getKind() == ElementKind.CLASS) {
            // 显示转换元素类型
            TypeElement typeElement = (TypeElement) element;
            // 输出元素名称
            System.out.println(typeElement.getSimpleName());
            // 输出注解属性值
            System.out.println(typeElement.getAnnotation(MyAnnotation.class).value());
        }
        System.out.println("------------------------------");
    }
    return false;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值