原理
- 定义编译期的注解
- 利用JSR269 API(Pluggable Annotation Processing API)创建编译期的注解处理器
- 利用tools.jar的javac api处理AST(抽象语法树)
- 将功能注册jar包
实现
创建Getter注解的处理器
继承AbstractProcessor这个类,基本的框架大体如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17package com.mythsman.test;
import javax.annotation.processing.*;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.TypeElement;
import java.util.Set;
"com.mythsman.test.Getter") (
(SourceVersion.RELEASE_8)
public class GetterProcessor extends AbstractProcessor {
public synchronized void init(ProcessingEnvironment processingEnv) {
super.init(processingEnv);
}
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
return true;
}
}
需要着重实现两个方法:
- init : 通过ProcessingEnvironment来获取编译阶段的一些环境信息
- process:主要实现具体逻辑的地方,也就是对AST进行处理的地方
init方法
1 | private Messager messager; |
process方法
1 |
|
接下来再实现makeGetterMethodDecl方法:1
2
3
4
5
6
7
8
9
10private JCTree.JCMethodDecl makeGetterMethodDecl(JCTree.JCVariableDecl jcVariableDecl) {
ListBuffer<JCTree.JCStatement> statements = new ListBuffer<>();
statements.append(treeMaker.Return(treeMaker.Select(treeMaker.Ident(names.fromString("this")), jcVariableDecl.getName())));
JCTree.JCBlock body = treeMaker.Block(0, statements.toList());
return treeMaker.MethodDef(treeMaker.Modifiers(Flags.PUBLIC), getNewMethodName(jcVariableDecl.getName()), jcVariableDecl.vartype, List.nil(), List.nil(), List.nil(), body, null);
}
private Name getNewMethodName(Name name) {
String s = name.toString();
return names.fromString("get" + s.substring(0, 1).toUpperCase() + s.substring(1, name.length()));
}