注解学习笔记 1

167 阅读2分钟

jkd1.8中文API (可以在API中查看相关类的说明,介绍很详细)
参考《Android进阶之光》第九章注解与依赖注入框架
学习时不明白的地方,尽量要去查清楚,比如在学习编译时注解器时:AbstractProcessor不知道它是做什么的,就可以去查一下jdk1.8中文API有比较详细的解释;这样学下来,可能刚开始学的慢,但是学的比较深入,理解到位

注解概述

注解常用类型:
@Target:注解修饰的对象范围

  • ElementType.TYPE: 修饰类,接口或枚举类型
  • ElementType.FIELD:修饰成员变量
  • ElementType.PARAMETR:修饰参数
  • ElementType.METHOD:修饰方法
  • 等等 @Retention:声明注解的保留策略
  • Retention.RUNTIME: 运行时注解
  • Retention.SOURCE: 源码级注解
  • Retention.CLASS: 编译时注解

例子学习

1. 运行时注解处理器

定义注解

@Documented
@Retention(RetentionPolicy.RUNTIME) //保留策略为运行时
@Target(ElementType.METHOD)         //规定此注解修饰方法
public @interface Swordsman {
    String name() default "android";
    int age() default 10;
}


@Documented
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface GET {
    String value() default "192.168.0.1";
}

注解处理器

package annotation;

import java.lang.reflect.Method;

public class AnnotationProcessor {
    public static void main(String[] args) {
        //获取这个类的公共方法
        Method[] methods = AnnotationTest.class.getDeclaredMethods();
        //遍历这个类的公共方法
        for (Method method : methods){
            //判断这个方法是否有swordsman注解, Method ,Class, Filed等实现了AnnotatedElement
            if (method.isAnnotationPresent(Swordsman.class)){
                Swordsman swordsman1 = method.getAnnotation(Swordsman.class);
                System.out.println(" swordsman "+swordsman1.name());
            }
            //判断
            if (method.isAnnotationPresent(GET.class)){
                GET get =  method.getAnnotation(GET.class);
                System.out.println("Get 值 "+get.value());
            }

        }
    }
}

2.编译时注解处理器

Android buildGradle 在3.0版本之后采用 annotationProcessor加载注解库
定义注解

@Retention(RetentionPolicy.CLASS)
@Target(ElementType.FIELD)
public @interface BindView {
    int value() default 1;
}

注解解释器

//继承:AbstractProcessor
//@AutoService(Processor.class)
public class ClassProcessor extends AbstractProcessor {

    /**
     * @param processingEnvironment 由工具框架返回的处理环境
     */
    @Override
    public synchronized void init(ProcessingEnvironment processingEnvironment) {
        System.out.println("注解处理工具调用");
        super.init(processingEnvironment);
    }

    /**
     *
     * @param roundEnvironment 用于查询一轮注释处理的信息
     */
    @Override
    public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {
        //TODO  Messager 提供注释处理器报告错误消息,警告和其他通知的方式
        Messager messager = processingEnv.getMessager();
        //返回使用给定注释类型的元素
        for (Element element : roundEnvironment.getElementsAnnotatedWith(BindView.class)){
            //获取元素的类型 TODO: Element 表示程序元素,如程序包,类、方法、属性等
            if (element.getKind() == ElementKind.FIELD){
                //打印指定类型的属性名 在这里是打印属性名
                messager.printMessage(Diagnostic.Kind.NOTE,"printMessage: "+element.toString());
                //打印注解值
                messager.printMessage(Diagnostic.Kind.NOTE,"printMessage: "+element.getAnnotation(BindView.class).value());
            }
        }
        return true;
    }

    /**
     * 返回此处理器支持的注释类型的名称
     */
    @Override
    public Set<String> getSupportedAnnotationTypes() {
        //指定这个注解器是注册给哪个注解的
        Set<String> annotations = new LinkedHashSet<>();
        annotations.add(BindView.class.getCanonicalName());
        System.out.println("获取集合 : "+annotations);
        return annotations;
    }

    @Override
    public SourceVersion getSupportedSourceVersion() {
        //用来指定使用的Java版本
        return SourceVersion.latestSupported();
    }
}