分类: Java开发

JSR269 编译期处理常用操作

基础变量

后面有些凭空出现的变量可以从这找类型和获取方式:

JavacTrees trees = JavacTrees.instance(processingEnv);
Context context = ((JavacProcessingEnvironment)processingEnv).getContext();
TreeMaker treeMaker = TreeMaker.instance(context);
Names names = Names.instance(context);

JCTree jcTree = trees.getTree(element);
JCTree.JCCompilationUnit imports = (JCTree.JCCompilationUnit) trees.getPath(element).getCompilationUnit();

添加导入包

后面无论加接口还是加注解,都需要先导包:

JCTree.JCCompilationUnit imports = (JCTree.JCCompilationUnit) trees.getPath(element).getCompilationUnit();

imports.defs = imports.defs.append(
    treeMaker.Import(
        treeMaker.Select(
            treeMaker.Ident(names.fromString("cn.lzxz1234.somepackage")), 
            names.fromString("ClassName")), 
        false)
);

类添加接口声明

类添加继承序列化接口等操作

JCClassDecl var1 = xxxx;
var1.implementing = var1.implementing.append(treeMaker.Ident(names.fromString("Serializable")));

类添加注解

类声明的前面添加 @Service @Compoent 等各种类型的各种注解:

JCClassDecl var1 = xxxx;
var1.mods.annotations = var1.mods.annotations.append(treeMaker.Annotation(
    treeMaker.Ident(names.fromString("Api")), 
    List.nil()
));

注解取值

当前类上可能已经有注解了,如 @Api(version=1.0),要取 version 的值 1.0 那么可以通过 k.mods.annotations 过滤找到 JCAssign 然后取 rhs 的值即可:

JCVariableDecl decl = xxxx;
decl.mods.annotations.stream()
.filter(k -> k.annotationType.toString().contains("Api"))
.flatMap(k -> k.args.stream())
.forEach(k -> {
    if(k.getKind().equals(Kind.ASSIGNMENT)) {
        JCAssign assign = (JCAssign)k;
        if(assign.lhs.getKind().equals(Kind.IDENTIFIER) && (((JCIdent)assign.lhs).name).toString().equals("version")) {
            double version = (double)(((JCLiteral)assign.rhs).value);
        }

    }
});

判断变量类型

主要用于判断成员变量是不是静态的或者 final 的之类的

JCVariableDecl k;
k.mods.getFlags().contains(Modifier.STATIC);
k.mods.getFlags().contains(Modifier.FINAL);

字段上添加注解

基本的类型判断和是否已经存在注解就跳过了,直接展示操作:

JCVariableDecl decl = xxxx;
decl.mods.annotations = decl.mods.annotations.append(
    treeMaker.Annotation(
        treeMaker.Ident(names.fromString("Api")), 
        List.of(treeMaker.Assign(treeMaker.Ident(names.fromString("version")),
            treeMaker.Literal(sortId.incrementAndGet())))
    )
);

Recent Posts

Docker 容器非 root 用户监听 80 端口

起因是基于 CentOS 的 …

2 年 之前

基于 Docker 定时打印文件

先说背景,喷墨打印机有个很大的…

3 年 之前

Java 运行时反射获取来自继承的泛型

背景 正常情况下 Java 的…

3 年 之前

Java 基于 ByteBuddy 重写系统当前时间

背景 一般单元测试时总会有些代…

3 年 之前

华硕 B450F-Gaming 主板 I211-AT 网卡驱动安装

事情起因是买了块华硕的 ROG…

3 年 之前

PHP 安装 Memcached 扩展

登录服务器挨步执行: # su…

4 年 之前