Java注解与自定义注解处理器

动机

最近在看ButterKnife源码的时候,居然发现有一个类叫做AbstractProcessor,并且ButterKnife的View绑定不是依靠反射来实现的,而是使用了编译时的注解,自动生成的.class文件。真是一个神奇的东西啊!!

所以本文就注解与自定义的注解处理器来学习注解。项目Github地址

基础知识

大家应该知道元注解@Retention吧,它表示注解在什么时候存在,可以分为3个时期:

  • RetentionPolicy.SOURCE:表示注解只在java文件里面才有,在编译的时候,这部分注解就会被擦出。类似于@Override只是给程序员看的。
  • RetentionPolicy.CLASS:注解在编译的时候会存在,在运行的时候就会擦除。
  • RetentionPolicy.RUNTIME:在运行的时候会存在,这里就要用到了反射来实现了。

Annotation Processor

注解处理器,在编译期间,JVM会自动运行注解处理器(当然,我们需要将其注册)。虽然我们写的Java代码被编译成class就不能被改动了,但是注解处理器会重新生成其他的java代码,我们可以通过反射来调用新生成的java文件里面的类或方法。然后JVM再对这些生成的java代码进行编译。这是一个递归的过程。

Java API为我们提供了注解处理器的接口,我们只要实现它就可以了。这个类就是AbstractProcessor,下面就一起来实现它。这个例子我是从【Java二十周年】Java注解处理器,参考过来的。实现功能如下:对于一个类,只要给它的某个加上一个注解,就会自动生成其接口,接口中的方法就是加注解的方法。

public class Man {

    @Interface("ManInterface")
    public void eat() {
        System.out.println("Eat");
    }
}

eat方法加上了@Interface("ManInterface"),上述就会生成:

public interface ManInterface {
  void eat();
}

就是这么粗暴。
然后我们看看注解是怎么定义的:

package wqh.core;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * Created on 2016/8/10.
 *
 * @author 王启航
 * @version 1.0
 */
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.CLASS)
public @interface Interface {
   
    String value();
}

注意上面@Target(ElementType.METHOD)表示该方法只能加在方法上面;@Retention(RetentionPolicy.CLASS)表示是在编译时存在的。

好了接下来就是重点了:

public class InterfaceProcessor extends AbstractProcessor {
   

    @Override
    public synchronized void init(ProcessingEnvironment env){ }

    @Override
    public boolean process(Set<? extends TypeElement> annoations, RoundEnvironment env) { }

    @Override
    public Set<String> getSupportedAnnotationTypes() { }

    @Override
    public SourceVersion getSupportedSourceVersion() { }

}

定义自己的注解处理器

  • init对一些工具进行初始化。
  • process就是真正生成java代码的地方。
  • getSupportedAnnotationTypes表示该注解处理器可以出来那些注解。
  • getSupportedSourceVersion可以出来java版本

我们首先看看除去process的其他三个方法:

public class InterfaceProcessor extends AbstractProcessor {
   

    private Types typeUtils;
    private Elements elementUtils;
    private Filer filer;
    private Messager messager;


    @Override
    public synchronized void init(ProcessingEnvironment env) {
        super.init(env);
        elementUtils = env.getElementUtils();
        filer = env.getFiler();
        typeUtils = env.getTypeUtils();
        messager = env.getMessager();
    }

    @Override
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment env) {
    }

  
  • 4
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 9
    评论
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值