Jeta:如何创建自定义注释处理器
Jeta: How to create custom annotation processors
plenty of features 已在 Jeta
上可用,但如果缺少某些内容怎么办。我可以创建自己的注释并为其生成元代码吗?
需要有关如何创建自定义 Jeta
处理器的分步教程。
如何创建自定义处理器,分步教程
第 1 步:Hello, World
项目
对于本教程,让我们创建一个简单的 Gradle
项目,其中包含一个模块 app
和一个 class SayHelloApp
。 class 将 Hello, World!
写入标准输出。
为了说明,我们将创建 Hello
注释,将 Hello, Jeta!
字符串设置为注释字段。
第 2 步:common
模块
首先,我们需要一个可以在 app
和 apt
(即将创建)模块中访问的模块。在 common
模块中,我们需要两个 classes - Hello
注释和 HelloMetacode
接口:
第 3 步:apt
模块
apt
- 是一个模块,我们将在其中创建代码生成所需的所有 classes。对于本教程,我们需要一个处理器来处理我们的 Hello
注释。
请注意,此模块依赖于 common
模块,因此我们使用 Hello
注释作为超级构造函数的参数。通过这样做,我们对 Jeta
说我们需要用给定类型注释的所有元素。该模块还依赖于 jeta-apt
以访问 Jeta
classes.
第 4 步:处理器
已创建 SayHelloProcessor
现在什么都不做。让我们在其中添加一些逻辑。这里的想法是生成 java 代码,将 Hello, Jeta
字符串设置为用 Hello
.
注释的字段
请注意 Jeta
使用 JavaPoet
创建 java 源代码。 Square
的框架真的很棒。请在 GitHub.
上查看
首先,我们需要 metacode 实现 HelloMetacode
。为此,我们将向 builder
:
添加超级接口
MetacodeContext context = roundContext.metacodeContext();
ClassName masterClassName = ClassName.get(context.masterElement());
builder.addSuperinterface(ParameterizedTypeName.get(
ClassName.get(HelloMetacode.class), masterClassName));
接下来,通过创建void setHello(M master)
方法实现HelloMetacode
:
MethodSpec.Builder methodBuilder = MethodSpec.methodBuilder("setHello")
.addAnnotation(Override.class)
.addModifiers(Modifier.PUBLIC)
.returns(void.class)
.addParameter(masterClassName, "master");
最后,Hello
注释的每个元素的语句,即Jeta
通过roundContext
参数传入process
方法:
for (Element element : roundContext.elements()) {
String fieldName = element.getSimpleName().toString();
methodBuilder.addStatement("master.$L = \"Hello, Jeta\"", fieldName);
}
这是完整的 SayHelloProcessor
清单:
package org.brooth.jeta.samples.apt;
import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.MethodSpec;
import com.squareup.javapoet.ParameterizedTypeName;
import com.squareup.javapoet.TypeSpec;
import org.brooth.jeta.apt.MetacodeContext;
import org.brooth.jeta.apt.RoundContext;
import org.brooth.jeta.apt.processors.AbstractProcessor;
import javax.lang.model.element.Element;
import javax.lang.model.element.Modifier;
public class SayHelloProcessor extends AbstractProcessor {
public SayHelloProcessor() {
super(Hello.class);
}
@Override
public boolean process(TypeSpec.Builder builder, RoundContext roundContext) {
MetacodeContext context = roundContext.metacodeContext();
ClassName masterClassName = ClassName.get(context.masterElement());
builder.addSuperinterface(ParameterizedTypeName.get(
ClassName.get(HelloMetacode.class), masterClassName));
MethodSpec.Builder methodBuilder = MethodSpec.methodBuilder("setHello")
.addAnnotation(Override.class)
.addModifiers(Modifier.PUBLIC)
.returns(void.class)
.addParameter(masterClassName, "master");
for (Element element : roundContext.elements()) {
String fieldName = element.getSimpleName().toString();
methodBuilder.addStatement("master.$L = \"Hello, Jeta\"", fieldName);
}
builder.addMethod(methodBuilder.build());
return false;
}
}
第 5 步:元代码
代码生成 classes 所需的所有内容均已创建,我们已准备好尝试。但首先,我们需要添加 jeta.properties
文件以配置 Jeta
。您可以找到有关此文件的更多详细信息 on this page。该文件应位于根包中。对于我们的教程,其内容为:
metasitory.package=org.brooth.jeta.samples
processors.add=org.brooth.jeta.samples.apt.SayHelloProcessor
接下来,修改SayHelloApp
。我们将在其上放置 Hello
注释,而不是初始化 text
字段:
public class SayHelloApp {
@Hello
String text;
}
和build.gradle
:
group 'org.brooth.jeta-samples'
version '1.0'
buildscript {
repositories {
maven {
url 'https://plugins.gradle.org/m2/'
}
}
dependencies {
classpath 'net.ltgt.gradle:gradle-apt-plugin:0.5'
}
}
apply plugin: 'net.ltgt.apt'
apply plugin: 'java'
sourceCompatibility = 1.7
repositories {
mavenCentral()
jcenter()
}
compileJava {
options.sourcepath = files('src/main/java')
}
dependencies {
apt project(':apt')
compile project(':common')
compile 'org.brooth.jeta:jeta:+'
}
现在我们可以生成元代码了。 运行 控制台中的下一个命令:
./gradlew assemble
如果到目前为止没有问题,我们将在 app/build
目录下看到 SayHelloApp_Metacode
文件:
第 6 步:控制器
Controllers are the classes that apply metacode to the masters。让我们在 app
模块中为 HelloMetacode
创建一个:
package org.brooth.jeta.samples;
import org.brooth.jeta.MasterController;
import org.brooth.jeta.metasitory.Metasitory;
public class SayHelloController<M> extends MasterController<M, HelloMetacode<M>> {
public SayHelloController(Metasitory metasitory, M master) {
super(metasitory, master, Hello.class, false);
}
public void setHello() {
for (HelloMetacode<M> metacode : metacodes)
metacode.setHello(master);
}
}
第 7 步:MetaHelper
MetaHelper
是一个简单的静态助手 class。如果您对静态助手不满意,则不应在您的项目中使用它。您可以在 this page.
上阅读有关此 class 的更多详细信息
无论如何,让我们在app
模块中创建MetaHelper
:
package org.brooth.jeta.samples;
import org.brooth.jeta.metasitory.MapMetasitory;
import org.brooth.jeta.metasitory.Metasitory;
public class MetaHelper {
private static MetaHelper instance;
private final Metasitory metasitory;
public static MetaHelper getInstance() {
if (instance == null)
instance = new MetaHelper("org.brooth.jeta.samples");
return instance;
}
private MetaHelper(String metaPackage) {
metasitory = new MapMetasitory(metaPackage);
}
public static void setHello(Object master) {
new SayHelloController<>(getInstance().metasitory, master).setHello();
}
}
请注意,我们必须将我们在 jeta.properties
中指定为 metasitory.package
的相同包 ("org.brooth.jeta.samples"
) 传递给 MapMetasitory
。
第 8 步:用法
最后一步 - 我们调用 MetaHelper
的方法。这是 SayHelloApp
的完整列表:
package org.brooth.jeta.samples;
public class SayHelloApp {
@Hello
String text;
public SayHelloApp() {
MetaHelper.setHello(this);
}
public void sayHello() {
System.out.print(text);
}
public static void main(String[] args) {
new SayHelloApp().sayHello();
}
}
终于可以运行SayHelloApp
了。在控制台中我们应该看到:
Hello, Jeta
链接
快乐的代码生成! :)
plenty of features 已在 Jeta
上可用,但如果缺少某些内容怎么办。我可以创建自己的注释并为其生成元代码吗?
需要有关如何创建自定义 Jeta
处理器的分步教程。
如何创建自定义处理器,分步教程
第 1 步:Hello, World
项目
对于本教程,让我们创建一个简单的 Gradle
项目,其中包含一个模块 app
和一个 class SayHelloApp
。 class 将 Hello, World!
写入标准输出。
为了说明,我们将创建 Hello
注释,将 Hello, Jeta!
字符串设置为注释字段。
第 2 步:common
模块
首先,我们需要一个可以在 app
和 apt
(即将创建)模块中访问的模块。在 common
模块中,我们需要两个 classes - Hello
注释和 HelloMetacode
接口:
第 3 步:apt
模块
apt
- 是一个模块,我们将在其中创建代码生成所需的所有 classes。对于本教程,我们需要一个处理器来处理我们的 Hello
注释。
请注意,此模块依赖于 common
模块,因此我们使用 Hello
注释作为超级构造函数的参数。通过这样做,我们对 Jeta
说我们需要用给定类型注释的所有元素。该模块还依赖于 jeta-apt
以访问 Jeta
classes.
第 4 步:处理器
已创建 SayHelloProcessor
现在什么都不做。让我们在其中添加一些逻辑。这里的想法是生成 java 代码,将 Hello, Jeta
字符串设置为用 Hello
.
请注意 Jeta
使用 JavaPoet
创建 java 源代码。 Square
的框架真的很棒。请在 GitHub.
首先,我们需要 metacode 实现 HelloMetacode
。为此,我们将向 builder
:
MetacodeContext context = roundContext.metacodeContext();
ClassName masterClassName = ClassName.get(context.masterElement());
builder.addSuperinterface(ParameterizedTypeName.get(
ClassName.get(HelloMetacode.class), masterClassName));
接下来,通过创建void setHello(M master)
方法实现HelloMetacode
:
MethodSpec.Builder methodBuilder = MethodSpec.methodBuilder("setHello")
.addAnnotation(Override.class)
.addModifiers(Modifier.PUBLIC)
.returns(void.class)
.addParameter(masterClassName, "master");
最后,Hello
注释的每个元素的语句,即Jeta
通过roundContext
参数传入process
方法:
for (Element element : roundContext.elements()) {
String fieldName = element.getSimpleName().toString();
methodBuilder.addStatement("master.$L = \"Hello, Jeta\"", fieldName);
}
这是完整的 SayHelloProcessor
清单:
package org.brooth.jeta.samples.apt;
import com.squareup.javapoet.ClassName;
import com.squareup.javapoet.MethodSpec;
import com.squareup.javapoet.ParameterizedTypeName;
import com.squareup.javapoet.TypeSpec;
import org.brooth.jeta.apt.MetacodeContext;
import org.brooth.jeta.apt.RoundContext;
import org.brooth.jeta.apt.processors.AbstractProcessor;
import javax.lang.model.element.Element;
import javax.lang.model.element.Modifier;
public class SayHelloProcessor extends AbstractProcessor {
public SayHelloProcessor() {
super(Hello.class);
}
@Override
public boolean process(TypeSpec.Builder builder, RoundContext roundContext) {
MetacodeContext context = roundContext.metacodeContext();
ClassName masterClassName = ClassName.get(context.masterElement());
builder.addSuperinterface(ParameterizedTypeName.get(
ClassName.get(HelloMetacode.class), masterClassName));
MethodSpec.Builder methodBuilder = MethodSpec.methodBuilder("setHello")
.addAnnotation(Override.class)
.addModifiers(Modifier.PUBLIC)
.returns(void.class)
.addParameter(masterClassName, "master");
for (Element element : roundContext.elements()) {
String fieldName = element.getSimpleName().toString();
methodBuilder.addStatement("master.$L = \"Hello, Jeta\"", fieldName);
}
builder.addMethod(methodBuilder.build());
return false;
}
}
第 5 步:元代码
代码生成 classes 所需的所有内容均已创建,我们已准备好尝试。但首先,我们需要添加 jeta.properties
文件以配置 Jeta
。您可以找到有关此文件的更多详细信息 on this page。该文件应位于根包中。对于我们的教程,其内容为:
metasitory.package=org.brooth.jeta.samples
processors.add=org.brooth.jeta.samples.apt.SayHelloProcessor
接下来,修改SayHelloApp
。我们将在其上放置 Hello
注释,而不是初始化 text
字段:
public class SayHelloApp {
@Hello
String text;
}
和build.gradle
:
group 'org.brooth.jeta-samples'
version '1.0'
buildscript {
repositories {
maven {
url 'https://plugins.gradle.org/m2/'
}
}
dependencies {
classpath 'net.ltgt.gradle:gradle-apt-plugin:0.5'
}
}
apply plugin: 'net.ltgt.apt'
apply plugin: 'java'
sourceCompatibility = 1.7
repositories {
mavenCentral()
jcenter()
}
compileJava {
options.sourcepath = files('src/main/java')
}
dependencies {
apt project(':apt')
compile project(':common')
compile 'org.brooth.jeta:jeta:+'
}
现在我们可以生成元代码了。 运行 控制台中的下一个命令:
./gradlew assemble
如果到目前为止没有问题,我们将在 app/build
目录下看到 SayHelloApp_Metacode
文件:
第 6 步:控制器
Controllers are the classes that apply metacode to the masters。让我们在 app
模块中为 HelloMetacode
创建一个:
package org.brooth.jeta.samples;
import org.brooth.jeta.MasterController;
import org.brooth.jeta.metasitory.Metasitory;
public class SayHelloController<M> extends MasterController<M, HelloMetacode<M>> {
public SayHelloController(Metasitory metasitory, M master) {
super(metasitory, master, Hello.class, false);
}
public void setHello() {
for (HelloMetacode<M> metacode : metacodes)
metacode.setHello(master);
}
}
第 7 步:MetaHelper
MetaHelper
是一个简单的静态助手 class。如果您对静态助手不满意,则不应在您的项目中使用它。您可以在 this page.
无论如何,让我们在app
模块中创建MetaHelper
:
package org.brooth.jeta.samples;
import org.brooth.jeta.metasitory.MapMetasitory;
import org.brooth.jeta.metasitory.Metasitory;
public class MetaHelper {
private static MetaHelper instance;
private final Metasitory metasitory;
public static MetaHelper getInstance() {
if (instance == null)
instance = new MetaHelper("org.brooth.jeta.samples");
return instance;
}
private MetaHelper(String metaPackage) {
metasitory = new MapMetasitory(metaPackage);
}
public static void setHello(Object master) {
new SayHelloController<>(getInstance().metasitory, master).setHello();
}
}
请注意,我们必须将我们在 jeta.properties
中指定为 metasitory.package
的相同包 ("org.brooth.jeta.samples"
) 传递给 MapMetasitory
。
第 8 步:用法
最后一步 - 我们调用 MetaHelper
的方法。这是 SayHelloApp
的完整列表:
package org.brooth.jeta.samples;
public class SayHelloApp {
@Hello
String text;
public SayHelloApp() {
MetaHelper.setHello(this);
}
public void sayHello() {
System.out.print(text);
}
public static void main(String[] args) {
new SayHelloApp().sayHello();
}
}
终于可以运行SayHelloApp
了。在控制台中我们应该看到:
Hello, Jeta
链接
快乐的代码生成! :)