• 编译期间生成代码(Lombok原理)


    通过在编译期间,修改Java的AST(Abstract Syntax Tree)树,可以往类中,添加/修改(覆盖)方法、属性等。

    现在比较常见的三方依赖例子有:Lobbok的@Data可以生成get、set方法,@Sl4j2可以生成静态常量log。

    这篇文章,主要通过代码展示如何生成get、set方法。

    编写一个只在编译期存在的注解:

    import java.lang.*;
    
    @Target({ElementType.TYPE})
    @Retention(RetentionPolicy.SOURCE)
    public @interface Data {    
        
    }
    

    注解增强器

    Java 编译器对注解的操作,是通过继承AbstractProcessor来实现的。如下是一个添加setter方法:

    流程:

    1. 初始化参数操作,见init方法
    2. 在process方法中。生成方法。
    3. 先获取注解元素集合:
    4. 将注解元素转成class定义元素集合:
    5. 最后遍历class元素集合,获取其属性,并生成方法,修改dsfs树。

    过程代码涉及信息泄密,忽略。

    配置注解增强器

    遵循SPI(Service Provider interface),在resources/META-INF/services中配置注解增强器,项目结构结构如下:
    先忽略

    文件的内容如下,如果有多个增强器,按行配置即可:

    incremental.annotation.processors:

    com.huawei.fbb.cool.aspect.cool.data.DataProcessor,isolating1
    

    javax.annotation.processing.Processor:

    com.huawei.fbb.cool.aspect.cool.data.DataProcessor
    

    效果

    参考@Data编译后的class文件

    补充说明

    由于是编译时注解,注解增强器,一定要单独一个项目(项目A),然后打包给其它服务引用(项目B)。

    项目A的pom:

        <dependencies>
            <dependency>
                <groupId>com.sungroupId>
                <artifactId>toolsartifactId>
                <version>1.8version>
                <scope>systemscope>
                <systemPath>${java.home}/../lib/tools.jarsystemPath>
            dependency>
        dependencies>
        
        <build>
            <pluginManagement>
                <plugins>
                    <plugin>
                        <groupId>org.apache.maven.pluginsgroupId>
                        <artifactId>maven-compiler-pluginartifactId>
                        <configuration>
                            <source>1.8source>
                            <target>1.8target>
                        configuration>
                        <executions>
                            <execution>
                                <id>default-compileid>
                                <configuration>
                                    <compilerArgument>-proc:nonecompilerArgument>
                                configuration>
                            execution>
                            <execution>
                                <id>compile-projectid>
                                <phase>compilephase>
                                <goals>
                                    <goal>compilegoal>
                                goals>
                            execution>
                        executions>
                    plugin>
    
                plugins>
    
            pluginManagement>
    
        build>
    

    其中关于配置,可以用谷歌的 AutoService

    当前缺陷

    由于往AST插入方法元素,没有判断是否依据存在此类方法,所以很可能覆盖掉之前类中已经存在的方法

    解决

    增加方法之前,最好先判断一下是否已经含有这个的方法,如果有,就不插入。

  • 相关阅读:
    Leetcode Hot100之双指针
    本人开发Android视频编码和直播推流使用到的相关命令
    从Spring源码探究IOC初始化流程
    leetcode 210. 课程表 II 拓扑排序
    【MyBatisⅡ】动态 SQL
    哇,膜拜,师父竟然懂HARAKIRI的意思(附Linux常用命令)
    python 背包问题 动态规划
    golang 设置定时器time.NewTimer
    web前端课程设计——重庆旅游7页 HTML+CSS+JavaScript
    新手一定要看的嵌入式学习方法
  • 原文地址:https://blog.csdn.net/f_h_h/article/details/139754569