AbstractProcessor可用于设计类似lombok所做的功能。在我的代码中,我有如下注解:
@Retention(RetentionPolicy.SOURCE)
@Target({ElementType.TYPE, ElementType.METHOD})
public @interface OnTransform {
}
然后我创建了一个类,并在我的方法上注解了这个注解,如下所示:
public class TargetClass {
@OnTransform
public int add(int a, int b) {
return a + b;
}
@OnTransform
public void say(String name) {
System.out.println("Hello " + name);
}
}
现在我想为这些带注解的方法添加try finally块,所以我做了一个新的类扩展AbstractProcessor类,并完成了我的代码如下(实际上这部分代码主要来自ChatGPT):
public class TransformProcessor extends AbstractProcessor {
/**
* 初始化
* @param processingEnv environment to access facilities the tool framework
* provides to the processor
*/
@Override
public synchronized void init(ProcessingEnvironment processingEnv) {
super.init(processingEnv);
Context context = ((JavacProcessingEnvironment) this.processingEnv).getContext();
this.elementUtils = (JavacElements) this.processingEnv.getElementUtils();
this.messager = this.processingEnv.getMessager();
this.names = Names.instance(context);
this.trees = JavacTrees.instance(this.processingEnv);
this.treeMaker = TreeMaker.instance(context);
}
/**
* 用于在编译器打印消息的组件
*/
private Messager messager;
/**
* 用于创建标识符的对象
*/
private Names names;
/**
* 语法树
*/
private JavacTrees trees;
/**
* trees 和 elementUtils都可以获取 元素的JCTree对象
*/
private JavacElements elementUtils;
/**
* 用来构造语法树节点
*/
private TreeMaker treeMaker;
/**
* 字段的语法树节点的集合
*/
private List<JCTree.JCMethodDecl> methodDecls;
/**
* 允许支持的源码版本
* @return
*/
@Override
public SourceVersion getSupportedSourceVersion() {
if (SourceVersion.latest().compareTo(SourceVersion.RELEASE_8) > 0) {
return SourceVersion.latest();
} else {
return SourceVersion.RELEASE_8;
}
}
/**
* 允许支持的注解类型
* @return
*/
@Override
public Set<String> getSupportedAnnotationTypes() {
return ImmutableSet.of(OnTransform.class.getCanonicalName());
}
/**
* 代码增强处理
* @param annotations the annotation types requested to be processed
* @param roundEnv environment for information about the current and prior round
* @return
*/
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
Set<? extends Element> set = roundEnv.getElementsAnnotatedWith(OnTransform.class);
set.forEach(element -> {
JCTree jcTree = trees.getTree(element);
jcTree.accept(new TreeTranslator() {
@Override
public void visitMethodDef(JCTree.JCMethodDecl method) {
// 运行父类方法
super.visitMethodDef(method);
// 获取方法体
JCTree.JCBlock body = method.body;
// 创建try语句块
JCTree.JCBlock tryBlock = createTryBlock(body);
// 创建finally语句块
JCTree.JCBlock finallyBlock = createFinallyBlock();
// 创建try-catch-finally语句块
JCTree.JCTry tryFinally = createTryCatchFinally(tryBlock, finallyBlock);
// 替换原来的方法体
method.body = treeMaker.Block(0, List.of(tryFinally));
}
});
});
return true;
}
//create try block
private JCTree.JCBlock createTryBlock(JCTree.JCBlock body) {
return treeMaker.Block(0, body.getStatements());
}
// create finally block
private JCTree.JCBlock createFinallyBlock() {
return treeMaker.Block(0, List.nil());
}
// create try-finally block
private JCTree.JCTry createTryCatchFinally(JCTree.JCBlock tryBlock, JCTree.JCBlock finallyBlock) {
JCTree.JCTry aTry = treeMaker.Try(tryBlock, List.nil(), finallyBlock);
return aTry;
}
}
我可以让我的项目编译成功,但. class文件似乎修改失败如下:
public class TargetClass {
public TargetClass() {
}
public int add(int a, int b) {
return a + b;
}
public void say(String name) {
System.out.println("Hello " + name);
}
}
我不知道为什么,我调试了代码,发现方法. body被改变了,但不知道为什么它没有正确地刷新到. class文件中。下面的代码不像预期的那样工作:
method.body = treeMaker.Block(0, List.of(tryFinally));
也许我用错了?
1条答案
按热度按时间jk9hmnmh1#
需要帮助,谷歌了很多,但没有喜欢