自定义注解(一)

注解是JDK1.5版本开始引入的一个特性,用于对代码进行说明,可以对包,类,接口,字段,方法参数,局部变量等进行标记
分三类:
1.java自带的标准注解,如@Override(重写某个方法),@Deprecated(标明某个类或方法过时),@SuppressWarnings(标明要忽略的警告)
2.一类是元注解,元注解用于定义注解的注解,包括@Retention(标明注解被保留的阶段),@Target(标明注解使用的范围),@Inherited(标明注解可继承),@Documented(标明是否生成javadoc文档)
3.自定义注解,可以根据自己的需求定义注解

作用:
1.生成文档,通过代码里标识的元数据生成javadoc文档
2.编译检查,通过代码里标识的元数据让编译器在编译期间,进行检查验证
3.编译时动态处理,编译时通过代码里表示的元数据动态处理,例如动态生成代码
4.运行时动态处理,运行时通过代码里表示的元数据动态处理,例如使用反射注入实例

android 的自定义注解
要使用元注解来定义我们自定义的注解

元注解说明
@Target表明我们注解可以出现的地方。是一个ElementType枚举
@Retention这个注解的的存活时间
@Document表明注解可以被javadoc此类的工具文档化
@Inherited是否允许子类继承该注解,默认为false

@Target ElementType类型 说明:
ElementType.TYPE 接口、类、枚举、注解
ElementType.FIELD 字段
ElementType.METHOD 方法
ElementType.PARAMETER 方法参数
ElementType.CONSTRUCTOR 构造函数
ElementType.LOCAL_VARIABLE 局部变量
ElementType.ANNOTATION_TYPE 注解
ElementType.PACKAGE 包

@Retention RetentionPolicy类型 说明:
RetentionPolicy.SOURCE 注解只保留在源文件,当Java文件编译成class文件的时候,注解被遗弃
RetentionPolicy.CLASS 注解被保留到class文件,但jvm加载class文件时候被遗弃,这是默认的生命周期
RetentionPolicy.RUNTIME 注解不仅被保存到class文件中,jvm加载class文件之后,仍然存在

声明注解:
通过@Retention元注解确定我们注解使用时机,如上
通过@Target确定我们注解是作用在什么上面的

自定义注解分类:
**运行时注解,**在代码运行的过程中通过反射机制找到我们自定义的注解,然后做相应的事情
**编译时注解,**在编译的过程者中用javac注解处理器来扫描到我们自定义的注解,处理注解生成我们需要的一些文件(通常是java文件)

编译时注解:
1.声明注解
2.解析注解

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

编译时注解的解析需要我们自己实现一个注解解析处理器。注意处理器所作的工作,就是在代码编译过程中,找到指定我们的注解,然后加上自己特定的逻辑(通常生成java文件)
注意:要实现一个module必须是java-library(因为java library才能继承处理器AbstractProcessor)
goole为了方便我们注册注解处理器,提供一个注册处理器的库@AutoService(Processor.class)的注解来进行注册

添加依赖

dependencies {
    implementation 'com.google.auto.service:auto-service:1.0-rc2'
}
@AutoService(Process.class)
public class BindViewProcessor extends AbstractProcessor {
private Elements elements;
private Messager messager;
private Filer filer;
private Types types;

    /**
     * 注解处理器的核心方法,在这里来处理注解,并生成Java辅助类
     *
     * @param set
     * @param roundEnvironment
     * @return
     */
    @Override
    public boolean process(Set<? extends TypeElement> set, RoundEnvironment roundEnvironment) {
	Set<? extends Element> annotationElements = 	roundEnvironment.getElementsAnnotatedWith(BindView.class);
	for (Element element : annotationElements){
    	//获取字段名称
   	 if (element instanceof TypeElement) {
        		//注解用于类
        		try {
            	TypeElement typeElement2 = (TypeElement) element;
           	 System.out.println("typeElement2:" + typeElement2);
       	 	} catch (Exception e) {
            	e.printStackTrace();
        		}
    	} else { //注解用于字段
    		}
	}
        return false;
    }

    /**
     * 编译期间,init()会自动被注解处理工具调用,并传入ProcessingEnvironment参数,
     * 通过该参数可以获取到很多有用的工具类(Elements,Filer,Messager等)
     */
    @Override
    public synchronized void init(ProcessingEnvironment processingEnv) {
        super.init(processingEnv);
		elements = processingEnv.getElementUtils();
		messager = processingEnv.getMessager();
		filer = processingEnv.getFiler();
		types = processingEnv.getTypeUtils();

    }

    /**
     * 返回processor可处理的注解
     *
     * @return
     */
    @Override
    public Set<String> getSupportedAnnotationTypes() {
        Set<String> sets = new HashSet<>();
        sets.add(BindView.class.getCanonicalName());
        return sets;
    }


    /**
     * 用于指定你的java版本,一般返回:SourceVersion.latestSupported()
     */
    @Override
    public SourceVersion getSupportedSourceVersion() {
        return super.getSupportedSourceVersion();
    }
}

process()方法的核心是Element元素,Element代表程序的元素,在注解处理过程中,编译器会扫描所有的java源文件,并将源码中的每个部分都看作特定类型的Element
自定义处理器的过程除了要了解Element类和其它的子类,还需要4个帮助类:

注解处理器帮助类说明
Elements一个用来处理Element的工具类
Types一个用来处理TypeMirror的工具类
Filer用于创建文件(比如创建java文件)
Messager用于输出,类似print函数

这四个帮助类,可以通过在init()函数中,通过ProcessingEnvironment获取到

编写完注解处理器在app模块导入

implementation project(":模块名称")

在process函数中,通过RoundEnvironment可以返回得到使用给定注解的元素
源码:

public interface RoundEnvironment { 
    // 返回使用给定类型注解的元素。 
    Set<? extends Element> getElementsAnnotatedWith(TypeElement var1); 
    // 返回使用给定类型注解的元素。
    Set<? extends Element> getElementsAnnotatedWith(Class<? extends Annotation> var1);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值