安卓注解处理器-processor
最近在学习安卓开源框架发现,很多的开源框架都使用到了注解处理器,例如EventBus3.0。本文通过一个简单的Demo来介绍如何使用注解处理器。如果喜欢的话,欢迎大家给star。
Demo需求描述
用户通过执行一个传入参数为A(类对象)的静态方法,该方法会最终把参数A中加了特定注解的所有方法执行一遍。
需求实现
整个项目分为四个部分:
- 注解–要使用的注解类型,这部分通常也可以放在lib中;
- 注解处理器–要对注解进行处理的逻辑,包括收集有特定注解类型的方法信息以及生成特定的java文件;
- lib–封装合适的接口,供具体调用方调用;
- sample–具体的调用方逻辑。
首先新建一个安卓工程,点击运行展示的是hello world。
注解
在上述工程中new->Module->Java Library,新建一个Java Library Module,命名为annotation。在该Module下创建一个文件AnnotationTest.java,
AnnotationTest.java里面代码如下:
@Retention(RetentionPolicy.CLASS)
@Target(ElementType.METHOD)
public @interface AnnotationTest {String name() default "test";
}
1、注解@Retention按生命周期来划分可分为3类:
- RetentionPolicy.SOURCE:注解只保留在源文件,当Java文件编译成class文件的时候,注解被遗弃;
- RetentionPolicy.CLASS:注解被保留到class文件,当jvm加载class文件时候被遗弃,这是默认的生命周期;
- RetentionPolicy.RUNTIME:注解不仅被保存到class文件中,jvm加载class文件之后,仍然存在。
这3个生命周期分别对应于:Java源文件(.java文件) —> .class文件 —> 内存中的字节码。
2、注解@Target表示修饰的注解能使用的范围,ElementType.METHOD表示@AnnotationTest注解只能作用在方法上。
注解处理器
参照上部分,在工程中new->Module->Java Library,新建一个Java Library Module, 在该Module下创建一个文件ProcessorTest.java。在该Module下的build.gradle的dependencies中添加如下配置:
// 自动为processor注册
implementation 'com.google.auto.service:auto-service:1.0-rc2'
// 该Module依赖上部分建立的annotation Module
implementation project(':annotation')
com.google.auto.service:auto-service:1.0-rc2依赖的作用是为注解处理器自动注册,它会生成META-INF文件夹。
注解处理器ProcessorTest的定义如下,其中@AutoService(Processor.class)就是build.gradle中加的依赖帮助其自动注册。
@AutoService(Processor.class) // 自动为ProcessorTest注册,生成META-INF文件
public class ProcessorTest extends AbstractProcessor{
注解处理器ProcessorTest主要包含以下几个部分:
@Override
public synchronized void init(ProcessingEnvironment processingEnvironment) {super.init(processingEnvironment);mMessager = processingEnvironment.getMessager();mFiler = processingEnvironment.getFiler();
}
init方法是注解处理器会自动调用的初始化方法,其中mFiler是用来生成java源文件的工具,mMessager是用来打印日志的,它们的具体使用会在后面介绍。
@Override
public Set<String> getSupportedAnnotationTypes() {Set<String> supportAnnotationTypes = new HashSet<>();supportAnnotationTypes.add(AnnotationTest.class.getCanonicalName());return supportAnnotationTypes;
}
getSupportedAnnotationTypes()方法返回该注解处理器支持的注解类型,这里返回的就是我们之前声明的新的注解类型@AnnotationTest。
@Override
public SourceVersion getSupportedSourceVersion() {return SourceVersion.latestSupported();
}
getSupportedSourceVersion()方法一般就按照上述实现就行。
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnvironment) {// 打印日志mMessager.printMessage(Diagnostic.Kind.NOTE, "process start");Map<String, List<String>> collectInfos = new HashMap<>();for (TypeElement annotation: annotations){Set<? extends Element> elements = roundEnvironment.getElementsAnnotatedWith(annotation);for (Element element: elements){// 检查element是否符合我们定义的规范if (!checkValid(element)){mMessager.printMessage(Diagnostic.Kind.NOTE, "checkValid not pass");return false;}else {ExecutableElement executableElement = (ExecutableElement) element;// 获取被注解的方法所在的类TypeElement typeElement = (TypeElement) executableElement.getEnclosingElement();// 获取类的全名,包括包名String classFullName = typeElement.getQualifiedName().toString();// 被注解的方法的名字String methodName = executableElement.getSimpleName().toString();List<String> methods = collectInfos.get(classFullName);if (methods == null){methods = new ArrayList<>();collectInfos.put(classFullName, methods);}methods.add(methodName);}}}for (Map.Entry<String, List<String>> entry: collectInfos.entrySet()){mMessager.printMessage(Diagnostic.Kind.NOTE, entry.getKey());// 生成java源文件createJavaFile(entry.getKey(), entry.getValue());}return true;
}
process方法是我们的主要逻辑处理的地方,主要逻辑就是收集所有有@AnnotationTest注解的方法以及其所在的类信息,然后根据每个类信息,生成一个新的类文件,并在新的类文件的特定方法中调用所有关联的注解方法。生成java源文件将使用Filer对象,具体如何使用请下载demo看源代码。
注:
1、当你点击buid project时,注解处理器将会执行,而Messager对象打印出来的日志信息可以在Gradle Console窗口中看到。
2、如果你在该Module中使用中文注解,因为该Module为java library,可能会报GBK编码错误,解决办法是在该Module的build.gradle中添加如下代码:
//指定编译的编码
tasks.withType(JavaCompile){options.encoding = "UTF-8"
}
Lib
在工程中new->Module->Android Library ,新建一个Android Library Module,封装接口给调用方使用,具体逻辑请参考demo。
最终该demo的功能是点击Hello world文字,会依此执行MainActivity中使用@AnnotationTest注解的方法。
安卓注解处理器-processor相关推荐
- Kotlin版注解处理器Annotation Processor
文章目录 什么是注解 创建注解 什么是注解处理器 编写注解处理器 使用注解处理器生成代码 在Android项目中使用注解处理器 调试注解处理器 在处理器中记录日志和处理错误 分析种类.数据类型和可见性 ...
- 注解处理器(Annoation Processor)
前言 Java中的注解(Annotation)如果要被识别,离不开注解处理器.所以有必要来了解一下. 注解处理器 注解处理器(Annotation Processor)是javac的一个工具,不管是运 ...
- JAVA 注解 processor_注解处理器(Annotation Processor)简析
概念 注解处理器(Annotation Processor)是javac内置的一个用于编译时扫描和处理注解(Annotation)的工具.简单的说,在源代码编译阶段,通过注解处理器,我们可以获取源文件 ...
- 秒懂Android注解处理器(Android Annotation Processor)
[版权申明]非商业目的可自由转载 博文地址:https://blog.csdn.net/ShuSheng0007/article/details/90734159 出自:shusheng007 文章目 ...
- Java编译时注解处理器(Annotation Processor)详解
上篇文章我们使用注解+反射实现了一个仿ButterKnife功能的示例.考虑到反射是在运行时完成的,多少会影响程序性能.因此,ButterKnife本身并非基于注解+反射来实现的,而是用Annotat ...
- 基于注解处理器开发自动生成getter和setter方法的插件
昨天无意中,逛到了lombok的网站,并看到了首页的5分钟视频,视频中的作者只是在实体类中写了几个字段,就可以自动编译为含setter.getter.toString()等方法的class文件.看着挺 ...
- java 命名代码检查-注解处理器
命名代码检查 根据 <Java 语言规范( 第 3 版 ) > 中第6.8节的要求, Java 程序命名应当符合下列格式的书写规范: 类 ( 或接口 ) : 符合驼式命名法, 首字母大写. ...
- 【Android 组件化】路由组件 ( 注解处理器参数选项设置 )
文章目录 一.注解处理器 接收参数设置 二.注解处理器 生成路由表 Java 代码 三.博客资源 组件化系列博客 : [Android 组件化]从模块化到组件化 [Android 组件化]使用 Gra ...
- 【错误记录】Android 编译时技术报错 ( 注解处理器 process 方法多次调用问题 )
文章目录 一.报错信息 二.问题分析 三.解决方案 注解处理器 AbstractProcessor 中的 process 方法可能会调用多次 , 在生成代码时 , 一定要注意 , 检测到 注解节点 后 ...
最新文章
- ifelse的命令空间
- 总结:实例化SqlParameter时,如果是字符型,一定要指定size属性,还有制定具体的类型...
- linux 远程 telnet
- java springcloud版b2b2c社交电商spring cloud分布式微服务 (七)高可用的分布式配置中心(Spring Cloud Config)...
- LVS技术浅析-proc参数
- antd 3升级命令_是时候拥有一个你自己的命令行工具了
- webservice学习01:wsdl文档结构
- POJ 2117 Electricity 割点 Tarjan算法
- 程序员面试金典——3.4汉诺塔
- EXPLAIN mysql性能调优
- ARM开发7.3.4 基础实训( 4 ) 矩阵式键盘的输入系统设计--LPC21XX
- 中国 AI 天才养成计划:清华姚班和 100 个「张小龙」
- 斯托克斯定理,de Rham上同调习题
- 使用脚注添加网页类参考文献(使用word)
- 三菱FX5U以太网数据采集方案
- 【洛谷】P5149 会议座位
- mac bigsur python3.8 安装pillow失败
- 使用ML.NET实现德州扑克牌型分类器
- java 获取叶子节点个数_数据结构编程: 统计二叉树中叶子结点的个数。
- 用一分钟理解console的这个原理,多留几根黑发~