当前位置: 首页 > 工具软件 > JavaPoet > 使用案例 >

自定义注解生成代码(一) 之 javaPoetAPI详解

谢英光
2023-12-01

自定义注解生成代码(一) —— javaPoetAPI详解

目录

1. 前言

2. JavaPoet的常用类

3. JavaPoet的常用方法

  3.1 通用方法

     3.1.1 设置修饰关键字

     3.1.2 设置注解对象

     3.1.3 设置注释

   3.2 生成类、接口、枚举对象

     3.2.1 创建类

     3.2.2 创建接口

     3.2.3 创建枚举

   3.3 继承、实现接口

     3.3.1 继承类

     3.3.2 实现接口

     3.3.3 继承存在泛型的父类

   3.4 java类添加方法

   3.5 java类添加枚举

   3.6 注解

   3.7 修饰符

   3.8 注释

   3.9 实例化

   3.10 JavaPoet生成方法

     3.10.1 构造方法

     3.10.2 常规方法

     3.10.3 方法参数

     3.10.4 返回值

     3.10.5 方法体

     3.10.6 方法体模板

     3.10.7 $T 的使用的父类

     3.10.8 $N 的使用

     3.10.9 $S 的使用

     3.10.10 抛出异常

     3.10.11 添加修饰符

     3.10.12 添加注解

     3.10.13 设置属性

   3.11 JavaPoet生成代码

     3.11.1 生成代码

     3.11.2 代码打印到控制台

     3.11.3 代码输出到文件




1. 前言

最近发现一个有趣的库,javapoet翻译后就是java诗人,总而言之就是可以辅助我们在代码编译期间生成java代码,内部有良好的java格式并且可以完成自动导包,嗯真香。


2. JavaPoet的常用类

类名说明
JavaFile用于构造输出包含一个顶级类的Java文件(控制生成的Java文件的输出的类)
TypeSpec生成类,接口,或者枚举
MethodSpec生成构造函数或方法
FieldSpec生成成员变量或字段
ParameterSpec用来创建参数
AnnotationSpec用来创建注解
ClassName通过包名和类名生成的对象,在JavaPoet中相当于为其指定Class
ParameterizedTypeName通过MainClass和IncludeClass生成包含泛型的Class


3. JavaPoet的常用方法


3.1 通用方法


3.1.1 设置修饰关键字

addModifiers(Modifier... modifiers)

Modifier 是一个枚举对象,枚举值为修饰关键字 Public、Protected、Private、Static、Final 等等。
所有在JavaPoet创建的对象都必须设置修饰符(包括方法、类、接口、枚举、参数、变量)。


3.1.2 设置注解对象

addAnnotation(AnnotationSpec annotationSpec)
addAnnotation(ClassName annotation)
addAnnotation(Class<?> annotation)

该方法即为类或方法或参数设置注解,参数即可以是 AnnotationSpec,也可以是ClassName,还可以直接传递 Class 对象。
一般情况下,包含复杂属性的注解一般用 AnnotationSpec,如果单纯添加基本注解,无其他附加属性可以直接使用 ClassName 或者 Class 即可。


3.1.3 设置注释

addJavadoc(CodeBlock block)
addJavadoc(String format, Object... args)

在编写类、方法、成员变量时,可以通过addJavadoc来设置注释,可以直接传入String对象,或者传入CodeBlock(代码块)。


3.2 生成类、接口、枚举对象


JavaPoet 中生成类、接口、枚举,必须得通过 TypeSpec 生成,而 classBuilder、interfaceBuilder、enumBuilder 便是创建其关键的方法:

3.2.1 创建类

TypeSpec.classBuilder("类名“) 
TypeSpec.classBuilder(ClassName className)

3.2.2 创建接口

TypeSpec.interfaceBuilder("接口名称")
TypeSpec.interfaceBuilder(ClassName className)

> 3.2.3 创建枚举
TypeSpec.enumBuilder("枚举名称")
TypeSpec.enumBuilder(ClassName className)


3.3 继承、实现接口



3.3.1 继承类

.superclass(ClassName className)

> 3.3.2 实现接口
.addSuperinterface(ClassName className)  

3.3.3 继承存在泛型的父类

当继承父类存在泛型时,需要使用ParameterizedTypeName

ParameterizedTypeName get(ClassName rawType, TypeName... typeArguments)

返回的ParameterizedTypeName对象,已经被添加泛型信息



3.4 java类添加方法

addMethod(MethodSpec methodSpec)

通过配置MethodSpec对象,使用addMethod方法将其添加进TypeSpec中。


3.5 java类添加枚举

addEnumConstan(String enumValue)

通过addEnumConstan方法添加枚举值,参数为枚举值名称。

JavaPoet生成成员变量

JavaPoet生成成员变量是通过FieldSpecbuild方法生成.

builder(TypeName type, String name, Modifier... modifiers)

只要传入TypeName(Class)、name(名称)、Modifier(修饰符),就可以生成一个基本的成员变量。

成员变量一般来说由注解(Annotation)、修饰符(Modifier)Javadoc(注释)、initializer(实例化)。


3.6 注解

addAnnotation(TypeName name) 

3.7 修饰符

addModifiers(Modifier ...modifier)

3.8 注释

addJavadoc(String format, Object... args)

由于上述三个方法,都在通用方法介绍过这里就不再重复介绍。


3.9 实例化

initializer(String format, Object... args)

即成员变量的实例化,例:

public Activity mActivity = new Activity;

initializer 方法中的内容就是"="后面的内容,下面看下具体的代码实现,上面的成员变量:

  ClassName activity = ClassName.get("android.app", "Activity");
  FieldSpec spec = FieldSpec.builder(activity, "mActivity")
                .addModifiers(Modifier.PUBLIC)
                .initializer("new $T", activity)
                .build();

3.10 JavaPoet生成方法

JavaPoet生成方法分为两种,第一种是构造方法,另一种为常规的方法。


3.10.1 构造方法

MethodSpec.constructorBuilder()

3.10.2 常规方法

MethodSpec.methodBuilder(String name)

方法的主要构成有方法参数、注解、返回值、方法体、抛出异常五种,注解可以参考通用方法addAnnotation,其他方法我们将会一一介绍:


3.10.3 方法参数

addParameter(ParameterSpec parameterSpec)

设置方法参数的方法通过addParameterSpec来实现,ParameterSpec的具体使用参考下一小节。


3.10.4 返回值

returns(TypeName returnType)

设置方法的返回值,只需传入一个TypeName对象,而TypeNameClassName,ParameterizedTypeName的基类。


3.10.5 方法体

在JavaPoet中,设置方法体内容有两个方法,分别是addCodeaddStatement

addCode()

addStatement()

这两个本质上都是设置方法体内容,但是不同的是使用addStatement()方法时,你只需要专注于该段代码的内容,至于结尾的分号和换行它都会帮你做好。
addCode()添加的方法体内容就是一段无格式的代码片,需要开发者自己添加其格式。


3.10.6 方法体模板

在JavaPoet中,设置方法体使用模板是比较常见的,因为addCodeaddStatement方法都存在这样的一个重载:

addCode(String format, Object... args)

addStatement(String format, Object... args)

在JavaPoet中,format中存在三种特定的占位符:


3.10.7 $T 的使用

$T 在JavaPoet代指的是TypeName,该模板主要将Class抽象出来,用传入的TypeName指向的Class来代替。

ClassName bundle = ClassName.get("android.os", "Bundle");
addStatement("$T bundle = new $T()",bundle)

上述添加的代码内容为:

Bundle bundle = new Bundle();

3.10.8 $N 的使用

$N 在JavaPoet中代指的是一个名称,例如调用的方法名称,变量名称,这一类存在意思的名称

addStatement("data.$N()",toString)

上述代码添加的内容:

data.toString();

3.10.9 $S 的使用

$S 在JavaPoet中就和 String.format%s 一样,字符串的模板,将指定的字符串替换到$S的地方

.addStatement("super.$S(savedInstanceState)","onCreate")

即将"onCreate"字符串代替到$S的位置上.


3.10.10 抛出异常

.addException(TypeName name)

设置方法抛出异常,可以使用 addException 方法,传入指定的异常的 ClassName ,即可为该方法设置其抛出该异常.

JavaPoet生成方法参数
JavaPoet生成有参方法时,需要填充参数,而生成参数则需要通过 ParameterSpec 这个类。

addParameter(ParameterSpec parameterSpec)

初始化ParameterSpec

ParameterSpec.builder(TypeName type, String name, Modifier... modifiers)

给参数设置其Class,以及参数名称,和修饰符.

通常来说参数的构成包括:参数的类型(Class)、参数的名称(name) 、修饰符(modifiers) 、注解 (Annotation)

除了builder方法初始化类型、以及名称、修饰符之外,其余可以通过如下方法进行设置:


3.10.11 添加修饰符

.addModifiers(Modifier modifier)

常用的修饰符有 PUBLIC, PROTECTED, PRIVATE, ABSTRACT, DEFAULT, STATIC, FINAL, TRANSIENT, VOLATILE, SYNCHRONIZED, NATIVE, STRICTFP;


3.10.12 添加注解

addAnnotation(TypeName name) 

添加修饰符、注解具体使用可参考通用方法。

JavaPoet生成注解

在JavaPoet创建类、成员变量、方法参数、方法,都会用到注解。

如果使用不包含属性的注解可以直接通过

.addAnnotation(TypeName name)

直接传入 TypeName 或者 Class 进行设置。

如果使用的注解包含属性,并且不止一个时,这时候就需要生成 AnnotationSpec 来解决,下面简单了解下AnnotationSpec

初始化 AnnotationSpec

AnnotationSpec.builder(ClassName type)

可以发现初始化,只需传入 ClassName 或者 Class 即可。


3.10.13 设置属性

addMember(String name, String format, Object... args)

使用 addMember 可以设置注解的属性值,name 对应的就是属性名称,format 的内容即属性体,同样方法体的格式化在这里也是适用的。


3.11 JavaPoet生成代码


如果上述内容你已经看完,那么恭喜你,你已经明白JavaPoet的意图,但是现在的你,还差最后一步,即如何生成代码。


3.11.1 生成代码

JavaPoet中负责生成的类是JavaFile

JavaFile.builder(String packageName, TypeSpec typeSpec)

JavaFile 通过向 build 方法传入 PackageName(Java文件的包名)、TypeSpec(生成的内容) 生成。


3.11.2 代码打印到控制台

javaFile.writeTo(System.out)

生成的内容会输出到控制台中


3.11.3 代码输出到文件

javaFile.writeTo(File file)

生成的内容会以java文件的方式,存放到你传入File文件的位置

 类似资料: