借助Java APT去除样常见样板代码

Posted on 2025-08-04

概述

Coding过程中会遇到大量重复的的样板代码,有没有什么办法可以去掉这些样板代码呢?

本文将结合实际案例给出针对性的解决方案。

  1. 空校验:lombok.NonNull

img

一个合格的coder,多少是得有点【被迫害妄想】症状才行。

这种症状的体现在:不信任任何【输入】!在对输入进行逻辑处理前一定要先进行完整性校验,尤其是null

这种心态就会导致代码里出现大量的【卫语句】,比如上面的【if语句】。

借助lombok的编译器代码生成能力,可以去除这种【卫语句】。

img

img

编译前源码

编译后字节码

1. log变量:lombok.extern.slf4j.Slf4j

img

如上图,我们必须要在每个需要输出日志的地方,显式的、重复的声明类似的log字段。

【代码重复】是典型的坏味道!我们要解决这个事情。

借助lombok的编译器代码生成能力,可以去除这种重复代码!

img

img

编译前源码

编译后字节码

2. 依赖注入:lombok.RequiredArgsConstructor

img

如上图,在使用Spring依赖注入时,典型的代码就是上述的Autowired注解。

如果一个Bean的业务比较复杂,那么就是一大堆类似的字段声明,而且会看到一堆黄色告警。

img

告警提示说:不建议使用【字段注入】!

那咋办?

借助lombok的编译器代码生成能力,可以便捷的实现【构造器注入】。

img

img

编译前源码

编译后字节码

RequiredArgsConstructor注解会为所有final字段创建构造方法,而Spring会识别构造器参数以【构造器注入】。

3. 便捷组合:lombok.experimental.Delegate

img

如上图,有时候我们需要将【组合】的内部状态暴露到外部,一般来说我们只能重复的定义对应的getter方法。

但是借助lombok的编译器代码生成能力,可以实现便捷的方法委托。

img

img

编译前源码

编译后字节码(内部类在单独文件)

4. 资源清理:lombok.Cleanup

img

img

如上图,虽然try-with-resource是Java7新特性,但是它不好用,可读性也差!

但是借助lombok的编译器代码生成能力,可以实现便捷的【资源清理】。

img

img

编译前源码

编译后字节码

借助com.google.common.io.CloserAPI,甚至可以实现和Golang defer类似的效果!

img

5. 异常透传:lombok.SneakyThrows

img

如上图,有时候我们调用其他方法(二方/三方)时,需要处理一些checked异常。一般的处理是使用RuntimeException包裹后重新抛出。这种处理带来两个问题:

  1. 重复的代码:到处都是这种【捕获-包裹-抛出】式的样板代码。
  2. 上层丢失异常特征:将根因包裹后,上层代码无法case by casecatch处理。

但是借助lombok的编译器代码生成能力,可以绕过编译期异常捕获检查实现便捷的异常透传。

img

img

编译前源码

编译后字节码

原理详见:深入解析Lombok中的@SneakyThrows注解原理

6. SPI实现:com.google.auto.service.AutoService

img

img

如上图,当我们设计或实现SPI时,需要在META-INF目录下维护相应的元信息,用于运行时【扫描-发现】SPI实现。

既要写代码、又有维护配置,整体流程比较割裂。

1. 引入依赖


<dependency>
    <groupId>com.google.auto.service</groupId>
    <artifactId>auto-service</artifactId>
    <version>1.0.1</version>
    <optional>true</optional>
</dependency>

2. 使用注解

img

无需再手动维护META-INF目录下的配置信息,相关配置信息会在编译期自动生成。

总结

纸上得来终觉浅,这些技巧光看没用,需要自己见缝插针的找场景试试才会产生自己的理解。