⭐⭐⭐ Spring Boot 项目实战 ⭐⭐⭐ Spring Cloud 项目实战
《Dubbo 实现原理与源码解析 —— 精品合集》 《Netty 实现原理与源码解析 —— 精品合集》
《Spring 实现原理与源码解析 —— 精品合集》 《MyBatis 实现原理与源码解析 —— 精品合集》
《Spring MVC 实现原理与源码解析 —— 精品合集》 《数据库实体设计合集》
《Spring Boot 实现原理与源码解析 —— 精品合集》 《Java 面试题 + Java 学习指南》

摘要: 原创出处 juejin.cn/post/7538086111999459343 「AAA爱学习的刘哥」欢迎转载,保留摘要,谢谢!


🙂🙂🙂关注微信公众号:【芋道源码】有福利:

  1. RocketMQ / MyCAT / Sharding-JDBC 所有源码分析文章列表
  2. RocketMQ / MyCAT / Sharding-JDBC 中文注释源码 GitHub 地址
  3. 您对于源码的疑问每条留言都将得到认真回复。甚至不知道如何读源码也可以请教噢。
  4. 新的源码解析文章实时收到通知。每周更新一篇左右。
  5. 认真的源码交流微信群。

前言

本文不聊好不好,就跟大家唠唠几个超实用的小技巧!有些用法主要是图一乐,知道咋回事就行,至于要不要在实际开发里用,全看你自己的想法。毕竟每个程序员写代码的习惯都不一样,说不定这里面就有能戳中你的干货!花几分钟看完,保准能有点新收获~

正文

@onX 系列注解

像 onConstructor、onMethod 和 onParam 这类注解,能够在自动生成的代码中嵌入自定义注解。一个常见的应用场景是配合 Spring 的 @Autowired 注解。

在 Spring 组件(如 @Service、@Controller、@Component、@Repository 等)中使用 @RequiredArgsConstructor (onConstructor = @__(@Autowired)),可以让 Lombok 在生成构造函数时自动添加 @Autowired 注解,这样 Spring 就能自动注入所需的依赖。例如:

// 咱先给这个类加上@Service注解,表明它是Spring里的一个服务类
@Service
// 用@RequiredArgsConstructor注解,并且在构造函数上加上@Autowired注解来自动注入依赖
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class MyService {
// 声明一个不可变的AnotherService类型的成员变量,后续就能用它来调用AnotherService的方法啦
private final AnotherService anotherService;
}

上述代码经 Lombok 处理后,会生成以下代码:

// 这是一个Spring的服务类
@Service
public class MyService {
// 定义一个另一个服务类的成员变量,而且是final的,意味着赋值后就不能再变了
private final AnotherService anotherService;
// 通过构造函数注入anotherService,Spring会自动帮我们把对应的实例传进来
@Autowired
public MyService(AnotherService anotherService) {
this.anotherService = anotherService;
}
}

从生成的代码可以看出:

  • 为 MyService 类生成了一个接收 AnotherService 类型参数的构造函数。
  • 由于构造函数上添加了 @Autowired 注解,Spring 会自动查找合适的 AnotherService 实例并注入到 MyService 中。

这种方式结合了 Lombok 的代码自动生成功能和 Spring 的依赖注入特性,使代码更加简练。但使用时要确保团队成员都理解其原理,避免产生误解。

@Delegate 注解

@Delegate 能让某个类直接复用其他类的方法,无需手动编写转发代码。

比如,有一个类 A 包含 sayHello () 方法,若想让类 B 也能使用该方法,只需在类 B 中定义一个 A 类型的字段,并为其添加 @Delegate 注解,这样类 B 就能直接调用 sayHello () 方法,就像调用自身方法一样。示例如下:

// 包含一个方法的类
publicclass A {
public void sayHello() {
System.out.println("Hello");
}
}
// 委托了A类方法的类
publicclass B {
@Delegate// 委托A类的方法
private A a = new A();

public static void main(String[] args) {
B b = new B();
b.sayHello(); // 调用A类的方法
}
}

这种写法的最大优势是可以防止类继承层级过于复杂或耦合度偏高,从而增强代码的可读性和可维护性,毕竟多层继承确实容易让人看得眼花缭乱。

@Cleanup 注解

@Cleanup 能够自动处理 IO 流等资源的释放工作,确保安全调用 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 可用于集合类型字段,它会生成两个方法:一个用于添加单个元素,另一个用于添加整个集合。

这两个方法能与 @Builder 生成的其他方法配合进行链式调用,为类的所有字段赋值。或许这样说比较抽象,直接看示例:

@Data
@Builder
publicclass User {
private String name;
privateint age;
@Singular
private List<String> hobbies;
}
// 使用@Builder和@Singular生成的方法
User user = User.builder()
.name("张三")
.age(30)
.hobby("绘画") // 添加单个元素
.hobby("阅读") // 添加单个元素
.hobbies(Arrays.asList("旅行", "摄影")) // 添加整个集合
.build(); // 构造User对象

可见,使用 @Singular 注解的好处是能灵活地操作集合类型字段,不必自己动手创建和初始化集合实例。

此外,经 @Singular 注解处理的集合字段,在调用 build () 方法后会转为不可变集合,从而保证对象的不变性和线程安全性。你也可以使用 clear () 方法清空集合字段,例如:

User user = User.builder()
.name("晓宇")
.age(30)
.hobby("绘画")
.hobby("阅读")
.clearHobbies() // 清空集合字段
.hobby("摄影") // 重新添加元素
.build();

但需要注意的是,如果类继承了父类,@Builder 只会生成当前类的字段和参数,不包含父类的内容。

结尾

需要提醒的是,虽然 Lombok 提供了诸多便捷功能,但过度使用或使用不当可能会让代码变得难以理解和维护。因此,在使用这些功能时,务必保持谨慎,充分考虑其可能带来的影响。

文章目录
  1. 1. 前言
  2. 2. 正文
    1. 2.1. @onX 系列注解
    2. 2.2. @Delegate 注解
    3. 2.3. @Cleanup 注解
    4. 2.4. @Singular 与 @Builder 的组合使用
  3. 3. 结尾