前言

这篇文章不聊“对错”,只盘“骚操作”。
有些方法看看就好,知道 Lombok 还能这么用就够了;至于要不要搬进实际项目,那就见仁见智了。一万个读者心里有一万个哈姆雷特,希望下面的内容能给你带来一些启发。耐心看完,大概率会有收获。
@onX
例如 onConstructor、onMethod 和 onParam,它们能在 Lombok 生成代码时注入自定义注解。一个很典型的场景是配合 Spring 的 @Autowired 使用。
在 Spring 的组件(如 @Service、@Controller、@Component、@Repository 等)中,使用 @RequiredArgsConstructor(onConstructor = @__(@Autowired)),可以让 Lombok 生成构造函数时也带上 @Autowired 注解。这样一来,Spring 就能自动注入所需的依赖。
比如下面这段代码:
@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class MyService {
private final AnotherService anotherService;
}
上述代码片段经过 Lombok 处理后,会生成类似这样的代码:
@Service
public class MyService {
private final AnotherService anotherService;
@Autowired
public MyService(AnotherService anotherService) {
this.anotherService = anotherService;
}
}
从生成结果可以看出:
MyService 获得了一个接受 AnotherService 类型参数的构造函数。
- 由于构造函数上带有
@Autowired,Spring 会自动找到合适的 AnotherService bean 实例并注入。
这种写法把 Lombok 的自动代码生成和 Spring 的依赖注入结合了起来,能让代码干净不少。不过,这种“魔法”式的组合也依赖团队对 Lombok 和 Spring 的理解,用之前最好先在团队内达成共识,避免后面出现看不懂代码的情况。
@Delegate
@Delegate 可以让你的类直接使用其他类的方法,而不用自己再写一遍。
举个例子:类 A 里有一个 sayHello() 方法,你想让类 B 也能调用它,只需要在 B 中声明一个 A 类型的字段,并给它加上 @Delegate 注解。之后,B 就能像调用自己的方法一样直接调用 sayHello()。看代码:
// 一个类,有一个方法
public class A {
public void sayHello() {
System.out.println("Hello");
}
}
// 一个类,委托了A类的方法
public class B {
@Delegate // 委托A类的方法
private A a = new A();
public static void main(String[] args) {
B b = new B();
b.sayHello(); // 调用A类的方法
}
}
这样写最大的好处,就是可以避免类层次过深或耦合过紧,提升代码的可读性和可维护性。不然各种继承层层嵌套,阅读体验确实容易让人头疼。
@Cleanup
@Cleanup 可以自动管理输入输出流等需要释放的资源,确保安全地调用 close() 方法。
它的用法很简单,在声明资源时加上 @Cleanup 即可:
@Cleanup InputStream in = new FileInputStream("some/file");
代码执行完毕后,Lombok 会自动在 try-finally 块中调用 in.close(),帮你把资源释放掉。
如果释放资源的方法名不是 close,也可以显式指定方法名,例如:
@Cleanup("release") MyResource resource = new MyResource();
这样,Lombok 就会在 try-finally 块中自动调用 resource.release()。
相比于手动写 try-finally,@Cleanup 确实能让资源管理代码简洁很多。只要资源类提供了无参的释放方法,指定正确的方法名即可。
@Singular 和 @Builder 组合
@Builder 让类支持链式构造,而 @Singular 则让集合类型字段维护起来更方便。
@Singular 可以用在集合类型的字段上,Lombok 会生成两个方法:一个用于添加单个元素,另一个用于添加整个集合。这两个方法可以和 @Builder 生成的其它方法一起链式调用,完成对象构建。
光说可能有点抽象,直接看示例:
@Data
@Builder
public class User {
private String name;
private int age;
@Singular
private List<String> hobbies;
}
// 使用 @Builder 和 @Singular 生成的方法
User user = User.builder()
.name("练习时长两年半")
.age(28)
.hobby("篮球") // 添加单个元素
.hobby("唱歌") // 添加单个元素
.hobbies(Arrays.asList("跳舞", "其他")) // 添加整个集合
.build(); // 构造 User 对象
可以看出,@Singular 的好处在于:你可以灵活地向集合字段添加元素,而不需要手动创建和初始化集合对象。
另外,通过 @Singular 生成的集合字段,在调用 build() 之后会被转换为不可变集合。这样有利于保证对象的不变性和线程安全性。如果想要清空集合字段,也可以使用 clear() 方法:
User user = User.builder()
.name("签")
.age(28)
.hobby("说唱")
.hobby("跳舞")
.clearHobbies() // 清空集合字段
.hobby("踩缝纫机") // 重新添加元素
.build();
不过有一点需要注意:如果你的类继承了父类,@Builder 只会生成当前类的字段和参数,不会包含父类的字段。这在使用继承体系时需要特别留意。
@With
@With 允许你在当前对象的基础上创建一个新对象,新对象是原对象的副本,但某些字段的值已经被替换。
@With
public class Person {
private String name;
private int age;
}
Person person = new Person("Alice", 30);
// 创建一个新的 Person 对象,其 name 为 "Alice",但 age 为 31
Person updatedPerson = person.withAge(31);
在不可变对象场景中,@With 尤其好用。你不需要手写繁琐的“复制 + 修改”代码,直接调用 withXxx() 就能拿到更新后的实例。
结尾
最后提醒一句:Lombok 提供的功能确实很方便,但过度使用或不当使用,也可能会让代码变得难以理解和维护。
因此,做技术选型时还是要保持克制,充分考虑这些特性的影响,并与团队成员达成一致,再决定是否引入到具体项目中。