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. Hive学习之路 (十七)Hive分析窗口函数(五) GROUPING SETS、GROUPING__ID、CUBE和ROLLUP

    概述 GROUPING SETS,GROUPING__ID,CUBE,ROLLUP 这几个分析函数通常用于OLAP中,不能累加,而且需要根据不同维度上钻和下钻的指标统计,比如,分小时.天.月的UV数. ...

  2. Hive学习之路 (十六)Hive分析窗口函数(四) LAG、LEAD、FIRST_VALUE和LAST_VALUE

    数据准备 数据格式 cookie4.txt cookie1, ::,url2 cookie1, ::,url1 cookie1, ::,1url3 cookie1, ::,url6 cookie1, ...

  3. Hadoop学习之路(十五)MapReduce的多Job串联和全局计数器

    MapReduce 多 Job 串联 需求 一个稍复杂点的处理逻辑往往需要多个 MapReduce 程序串联处理,多 job 的串联可以借助 MapReduce 框架的 JobControl 实现 实 ...

  4. sed 以及 awk用法

    sed 格式 sed[options] "script" FILE.... 选项: -n:静默模式,不输出模式空间内的内容:默认打印空间模式的内容 -r:扩展的正则表达式 -f 文 ...

  5. mysql安装后找不到sock文件

    mysql rpm安装方式之后,启动找不到sock文件,经排查是之前安装的由mysql, 需要时yum list installed mysql 或者  rpm -qa |grep -i mysql ...

  6. Spring源码分析(六)解析和注册BeanDefinitions

    摘要:本文结合<Spring源码深度解析>来分析Spring 5.0.6版本的源代码.若有描述错误之处,欢迎指正. 当把文件转换为Document后,接下来的提取及注册bean就是我们的重 ...

  7. TCP建立连接与释放连接

    1.建立连接:(三次握手) (1)客户端发送一个SYN包给服务器,然后等待应答. (2)服务器端回应给客户端一个ACK=1.SYN=1的TCP数据段. (3)客户必须再次回应服务器端一个ACK确认数据 ...

  8. .Net操作Excel公式实现

    //传入Excel公式,获取公式计算结果private string GetValue(string formula) { string result = ""; try { Ob ...

  9. 12 Bit ADC与LSB的含义

    [转]12 Bit ADC与LSB的含义 LSB(Least Significant Bit),意为最低有效位:MSB(Most Significant Bit),意为最高有效位,若MSB=1,则表示 ...

  10. 逻辑卷管理-LVM(Logical Volume Manager)

    一. 概念与由来 LVM:逻辑卷管理(Logical Volume Manager) 普通的磁盘分区管理方式在逻辑分区划分好之后就无法改变其大小,当一个逻辑分区存放不下某文件时,这个文件因为受上层文件 ...