Take stock of several operations of Lombok, do you remember them?

For example, onConstructor, oMethod, and onParam allow you to inject custom annotations into the generated code. A common use case is in conjunction with Spring's @Autowired.

Using @RequiredArgsConstructor(onConstructor = @__(@Autowired)) in Spring components (such as @Service, @Controller, @Component, @Repository, etc.) allows Lombok to add the @Autowired annotation when generating the constructor, so , Spring can automatically inject the required dependencies.

For example, the following code

@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class MyService {
    private final AnotherService anotherService;
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.

The above code snippet uses Lombok and Spring annotations, and Lombok will generate the following code for it

@Service
public class MyService {
    private final AnotherService anotherService;

    @Autowired
    public MyService(AnotherService anotherService) {
        this.anotherService = anotherService;
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.

As can be seen from the generated code:

  • A constructor is generated for MyService that accepts a parameter of type AnotherService.
  • Due to the @Autowired annotation on the constructor, Spring will automatically find the appropriate AnotherService bean instance and inject it into MyService.

This method combines Lombok's automatic code generation function and Spring's dependency injection function to make the code more concise.

However, when using this technique make sure team members understand the meaning behind it to avoid confusion.

@Delegate

@Delegate allows your class to use methods of other classes without writing code yourself.

For example, if you have a class called A, it has a method called sayHello(), and you want another class B to also use this method, then you can add a field of type A to class B and add this field to Add the @Delegate annotation so that class B can directly call the sayHello() method as if it were its own method. Let’s look at an example:

// 一个类,有一个方法
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类的方法
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.

The biggest advantage of writing in this way is that it can avoid the class hierarchy being too deep or the coupling being too tight, and improve the readability and maintainability of the code. It is really a headache to inherit all kinds of inheritance.

@Cleanup

@Cleanup can automatically manage various resources that need to be released, such as input and output streams, to ensure that the close method is called safely.

It is used by adding @Cleanup before the declared resource, for example:

@Cleanup InputStream in = new FileInputStream("some/file");
  • 1.

In this way, when your code is executed, Lombok will automatically call the in.close() method in a try-finally block to release resources.

If the method name to release resources is not close, you can also specify the method name to be called, for example:

@Cleanup("release") MyResource resource = new MyResource();
  • 1.

Lombok will automatically call the resource.release() method in the try-finally block to release the resource.

As you can see, this is much simpler than manually writing try-finally. As long as you use @Cleanup, you can manage any resource with or without parameter methods and specify the correct method name.

@Singular and @Builder combination

@Builder allows your class to support chained construction, while @Singular allows collection type fields to be more easily maintained.

The @Singular annotation can be used on fields of collection type. It will generate two methods, one is to add a single element, and the other is to add the entire collection. These two methods can be chained together with other methods generated by @Builder to assign values ​​to all fields of your class.

It may be a bit confusing to say this, so just look at the example:

@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 对象
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.

As can be seen, the advantage of using the @Singular annotation is that you can flexibly add collection type fields without having to create and initialize the collection object yourself.

In addition, the collection fields generated using the @Singular annotation will be converted into immutable collections after calling the build() method, thus ensuring the object's immutability and thread safety. You can also use the clear() method to clear collection fields, for example:

User user = User.builder()
    .name("签")
    .age(28)
    .hobby("说唱")
    .hobby("跳舞")
    .clearHobbies() // 清空集合字段
    .hobby("踩缝纫机") // 重新添加元素
    .build();
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.

But it should be noted that if your class inherits a parent class, then @Builder will only generate the fields and parameters of the current class, excluding those of the parent class.

@With

Allows you to create a new object that is a copy of the current object, but with the values ​​of some fields changed.

@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);
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.

end

Note that although Lombok provides many convenient features, overuse or improper use can result in code that is difficult to understand and maintain.

Therefore, it is important to always exercise caution when using these features and fully consider their implications.