title: Annotation 使用备忘

date: 2018-01-02 20:48:43

tags: [Annotation]

categories: [Programming,Java]

概述

本文记录使用 javapoet 以及 auto-service 进行编译时注解的过程以及注意点.

最近又使用了一次编译时注解,期间产生了不少问题.

术语的解释

Element

这个代表被注解的元素.这个类有个很重要的方法,getEnclosingElement:这方法的含义是获取 包裹 element 最外围的元素.比如类的最外围的元素是 package.

    PackageElement pkgElement = (PackageElement) element.getEnclosingElement();

其他方法都很简单.

javapoet 库中一些重要的接口和方法

  1. TypeName: 对应了 java 代码中的一个类型元素,常用于声明一个方法参数,还有一些 collection 范型使用.
// 用来定一个 ComponentInfo 类的元素类型
TypeName mComponentInfoClassName = ClassName.get(ComponentInfo.class);
  1. ParameterizedTypeName 用来声明一个方法的参数.有个 get 方法,这个方法第一个参数是声明原生的类型,后面一个可变参数,声明第一个参数的参数.
// 声明一个参数的类型是 Map<String,List<ComponentInfo>>

ParameterizedTypeName paramListComponent = ParameterizedTypeName.get(ClassName.get(List.class), mComponentInfoClassName);
ParameterizedTypeName moduleLoaderParameter = ParameterizedTypeName.get(
ClassName.get(Map.class),
ClassName.get(String.class),
paramListComponent
);
  1. ParameterSpec

这个类代表方法的参数

// 声明一个方法的参数是:final Map<String,List<ComponentInfo>>  targetMap.
ParameterSpec injectParameterSpec = ParameterSpec.builder(moduleLoaderParameter, "targetMap", Modifier.FINAL).build();
  1. MethodSpec.Builder

    方法的构造器,用来构造一个方法.
// 用来构造一个私有方法,名字叫 inject ,参数是 Map<String,List<ComponentInfo>>  targetMap,String group,String pkg,String name,int type
MethodSpec.Builder injectElementBuilder = MethodSpec.methodBuilder("inject")
.addModifiers(Modifier.PRIVATE)
.addParameter(injectParameterSpec)
.addParameter(String.class, "group")
.addParameter(String.class, "pkg")
.addParameter(String.class, "name")
.addParameter(int.class, "type");

这个构造还可以继续添加语句

injectElementBuilder.addStatement("List<$T> list = targetMap.get(name)", ComponentInfo.class)
.beginControlFlow("if( list == null )")
.addStatement("list = new $T<>()", ArrayList.class)
.addStatement("targetMap.put(group, list)")
.endControlFlow()
.addStatement("ComponentInfo info = new ComponentInfo(type, group, pkg, name)")
.beginControlFlow("try")
.addStatement(" info.setClazz(Class.forName(pkg + name))")
.nextControlFlow("catch(Exception e)")
.addStatement("e.printStackTrace()")
.endControlFlow()
.addStatement("list.add(info)");

注意其中的两个 ControlFlow .

  1. TypeSpec

    用来声明一个类的描述
// 声明一个类,类名是 className,里面有两个方法
TypeSpec typeSpec = TypeSpec.classBuilder("className")
.addModifiers(Modifier.PUBLIC)
.addMethod(injectElementMethod)
.addMethod(injectMethodSpec)
.build();
  1. JavaFile

代表一个输出的 java 文件.

// 声明一个包名为 : com.steve.pkg 的java 文件.文件描述用的是一个 TypeSpec
JavaFile javaFile = JavaFile.builder("com.steve.pkg", typeSpec).build();

使用的注意事项

  1. 新版的 studio 以及不需要 android-apt
  2. 对于注解器的依赖可以通过 annotationProcessor project(':processor') 来对注解器工程进行依赖
  3. 对于注解配置选项可以在 gradle 中进行配置
defaultConfig {
minSdkVersion rootProject.ext.android.minSdkVersion
targetSdkVersion rootProject.ext.android.targetSdkVersion
versionCode rootProject.ext.android.versionCode
versionName rootProject.ext.android.versionName javaCompileOptions {
annotationProcessorOptions {
arguments = [moduleName: project.getName()]
}
} }
  1. 对于注解器的注册,@AutoService(Processor.class),不要写错了,写成 process
  2. 注解器的配置项需要在注解器中声明 @SupportedOptions("moduleName")
  3. 注解器中的 log 不要随便打 error,不然就会停止解析,这点和 android 中的 log 有些差异.

Annotation 使用备忘2的更多相关文章

  1. Annotation 使用备忘

    title: Annotation 使用备忘 date: 2016-11-16 23:16:43 tags: [Annotation] categories: [Programming,Java] - ...

  2. Spring boot 注解简单备忘

    Spring boot 注解简单备忘 1.定义注解 package com.space.aspect.anno;import java.lang.annotation.*; /** * 定义系统日志注 ...

  3. GIS部分理论知识备忘随笔

    文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/ 1.高斯克吕格投影带换算 某坐标的经度为112度,其投影的6度带和3度带 ...

  4. python序列,字典备忘

    初识python备忘: 序列:列表,字符串,元组len(d),d[id],del d[id],data in d函数:cmp(x,y),len(seq),list(seq)根据字符串创建列表,max( ...

  5. Vi命令备忘

    备忘 Ctrl+u:向文件首翻半屏: Ctrl+d:向文件尾翻半屏: Ctrl+f:向文件尾翻一屏: Ctrl+b:向文件首翻一屏: Esc:从编辑模式切换到命令模式: ZZ:命令模式下保存当前文件所 ...

  6. ExtJs4常用配置方法备忘

    viewport布局常用属性 new Ext.Viewport({ layout: "border", renderTo: Ext.getBody(), defaults: { b ...

  7. [备忘] Automatically reset Windows Update components

    这两天遇到Windows 10的更新问题,官方有一个小工具,可以用来修复Windows Update的问题,备忘如下 https://support.microsoft.com/en-us/kb/97 ...

  8. ECMAScript 5(ES5)中bind方法简介备忘

    一直以来对和this有关的东西模糊不清,譬如call.apply等等.这次看到一个和bind有关的笔试题,故记此文以备忘. bind和call以及apply一样,都是可以改变上下文的this指向的.不 ...

  9. MFC通过txt查找文件并进行复制-备忘

    MFC基于对话框的Demo txt中每行一个23位的卡号. 文件夹中包含以卡号命名的图像文件.(fpt或者bmp文件) 要求遍历文件夹,找到txt中卡号所对应的图像文件,并复制出来. VC6.0写的. ...

随机推荐

  1. Jython的应用

    今天本文围绕主要内容是jython是什么.安装.简单实用. 另外说说我为什么研究jython,研究它是有一个目的的,目的是将python代码转化为jar包以供安卓方面那边人脸识别,虽说目前人脸识别像阿 ...

  2. 51 Nod 1107 斜率小于0的连线数量 (转换为归并求逆序数或者直接树状数组,超级详细题解!!!)

    1107 斜率小于0的连线数量 基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题   二维平面上N个点之间共有C(n,2)条连线.求这C(n,2)条线中斜率小于0的线 ...

  3. 30秒搞定String面试

    Java 语言中,无论新菜鸟,还是老司机,真正了解String内存的很少.关于String 的试题,花样很多.== 在什么情况下是true,什么情况是false.我总结出如下3点让你彻底结束对Stri ...

  4. C++ 函数的二义性

    函数二义性是一种编译时发生的错误,造成二义性调用的原因 是在函数匹配时两个或多个函数提供的匹配一样好,编译时找 不到唯一的最佳匹配. 列: #include <iostream> usin ...

  5. 关于mysql-mybatis批量添加

    mybatis怎么实现一次插入多条数据   以后从新浪博客转到博客园这边来记录把.   这篇地址:http://blog.sina.com.cn/s/blog_13e9702640102ysho.ht ...

  6. PHP核心技术——面向对象

    类与对象: 类的定义与实例化. //定义类 class person{ public $name; public $gender; public function say(){ echo $this- ...

  7. CodeIgniter Doctrine2基本使用(二)(转)

    CodeIgniter Doctrine2基本使用(二) 继上次写的一篇文章<CodeIgniter Doctrine2基本使用(一)>写到操作实体的之通过Channel这个实体向数据库表 ...

  8. 总结sql用法及基础语法 第一章 三范式

    第一范式(1NF)设置了一个有组织的数据库非常基本的规则: 定义所需要的数据项,因为它们成为在表中的列.放在一个表中的相关的数据项. 确保有数据没有重复的组. 确保有一个主键. PRIMARY KEY ...

  9. JavaWeb总结(一)

    在学习Web应用程序客户端界面设计时,我们已经知道组成一个基本的Web应用程序需要Web服务器.Web客户端浏览器.HTTP协议以及静态HTML文件. Web服务器:接收客户端请求,然后向客户端返回一 ...

  10. exBSGS学习笔记

    exBSGS学习笔记 Tags:数学 题目的话就做下洛谷的模板好了 // luogu-judger-enable-o2 #include<algorithm> #include<io ...