Annotation 使用备忘2



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 有些差异.

原文地址:https://www.cnblogs.com/jnienv/p/10575575.html

时间: 2024-08-30 13:48:52

Annotation 使用备忘2的相关文章

Annotation 使用备忘

title: Annotation 使用备忘 date: 2016-11-16 23:16:43 tags: [Annotation] categories: [Programming,Java] --- 概述 本文记录注解 Annotation 的概念和使用. Annotation 注解 Why 需要注解 在代码中常有些重复的代码,这些代码纯手工太耗时.可以通过一定的标记,然后处理即可. What 是注解? Annotation 分类 标准 Annotation 包括 Override, De

备忘:hibernate, logback, slf4j实际应用一例

用hibernate写一些简单的数据库的Java应用.主要是温习一下.之前弄过的一些都忘了.发现还是得记下来,不然很快就忘. 1. Eclipse版本,用Juno, J2EE版本.最好下载zip版本的,直接解压就运行. 2. JDK安装,到Oracle上搜索jdk, 然后下载.安装JDK后,设置JAVA_HOME,指到JDK安装目录,将%JAVA_HOME%\bin放到PATH变量的最前面. 3. Maven.到Eclipse marketplace上搜索maven, 会有一个Maven Int

RxJava & RxAndroid备忘

"你问我要去向何方,我指着大海的方向" 今天在刷G+的时候看到Dave Smith推荐了一个视频 <Learning RxJava (for Android) by example> 点进去看了一下,原来是位熟悉的"阿三哥",视频封面如下:(没有歧视的意思,不要喷我啊~,为什么感到熟悉?接着往下看) 几乎同时也看到了JetBrains在G+也推荐了篇在Medium上的博文 <RxAndroid And Kotlin (Part 1)> ,然后

工作备忘:cacti&nagios登录密码修改方法

[[email protected]]# mysql -u root -p mysql> use cacti; mysql> select * from user_auth; mysql> update user_auth set password=md5("cactipasswd") where id='1'; 现在cacti登录的新密码就是cactipasswd [[email protected]]# /usr/bin/htpasswd /usr/local/n

备忘-linux文件系统结构

用apache的时候总是要进入/var/www, 用久了开始好奇这些个目录都是派什么用处的,简单整理了一下 /bin 存放二进制命令文件,这个目录下面不允许存在子目录/boot bootloader的静态文件,当然OS的文件也必须在这里/dev 设备文件,MAKEDEV命令可以创建设备/etc 特定主机的配置文件,必须是静态文件,非可执行文件: opt, X11, sgml, xml/home 用户目录 /lib 存放主要的共享库和核心模块/media 可移除媒体的挂载点: floppy, cd

[转]Windows环境下尝试安装并配置PHP PEAR备忘

转自:http://wangye.org/blog/archives/266/ 什么是PEAR 来自百度百科:PEAR 是PHP扩展与应用库(the PHP Extension and Application Repository)的缩写.它是一个PHP扩展及应用的一个代码仓库,简单地说,PEAR之于PHP就像是CPAN(Comprehensive Perl Archive Network)之于Perl. 由此可见PEAR是PHP代码的仓库,在这里可以找到很多有用的代码,避免我们重复写一些功能,

Table view 备忘

Table view 备忘 本篇会以备忘为主,主要是一些基础的代理方法和数据源方法具体的优化好点子会后续跟上. Table view的数据源方法 必须实现的数据源方法 // 返回每一行的cell,可以做缓存处理,同样也可能会造成复用问题. func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { // tableview 和 cell 都是在s

oracle下 启动subversion命令 及 oracle相关服务启动备忘

linux shell下  svnserve - d -r + 目录   例如:svnserve -d -r /svn 启动 svn服务. 访问svn://192.168.0.120/kjcg 测试. 启动oracle: 一.如何启动数据库实例 1.进入到sqlplus启动实例 [[email protected] ~]$ su - oracle --“切换到oracle用户” 2. Password: [[email protected] ~]$ lsnrctl start  --“打开监听”

linux下常用命令备忘

转自:Linux 命令集锦 linux下查看监听端口对应的进程 # lsof -i:9000 # lsof -Pnl +M -i4 如果退格键变成了:"^h". 终端连接unix删除退格键,按住CTL键同时按delete Linux搜索 # find / -name "xxx.conf" 查看linux是32位还是64位的命令 #file /sbin/init #getconf LONG_BIT #getconf -a 在Linux和Windows下都可以用nslo