Unlock Cleaner Java Code: Master Lombok’s @Delegate, @Cleanup, @Builder & More

Explore how Lombok’s powerful annotations—@onX, @Delegate, @Cleanup, @Singular, and @Builder—can dramatically simplify Java code, enable seamless Spring dependency injection, manage resources automatically, and streamline object construction, while highlighting best practices and potential pitfalls for maintainable backend development.

Java Backend Technology
Java Backend Technology
Java Backend Technology
Unlock Cleaner Java Code: Master Lombok’s @Delegate, @Cleanup, @Builder & More

Preface

This article does not discuss right or wrong, only showcases clever tricks. Some techniques are worth reading, but whether to apply them in real development is up to the reader.

One thousand readers will have a thousand Hamlets; hopefully this article sparks some thoughts.

Read patiently and you will gain something.

Body

@onX

For example onConstructor, onMethod, and onParam allow you to inject custom annotations into generated code. A common use case is combining with Spring’s @Autowired.

In Spring components such as @Service, @Controller, @Component, or @Repository, you can use @RequiredArgsConstructor(onConstructor = @__(@Autowired)) so Lombok adds @Autowired to the generated constructor, enabling Spring to inject the required dependency.

Example code:

@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class MyService {
    private final AnotherService anotherService;
}

Lombok then generates:

@Service
public class MyService {
    private final AnotherService anotherService;

    @Autowired
    public MyService(AnotherService anotherService) {
        this.anotherService = anotherService;
    }
}

The generated constructor receives an AnotherService parameter, and Spring automatically finds and injects the appropriate bean.

This combination makes the code more concise, but the team must understand the semantics to avoid confusion.

@Delegate

@Delegate

lets a class use methods of another class without writing boilerplate code.

For instance, class B can delegate to class A’s sayHello() method by declaring a field of type A annotated with @Delegate.

// Class A with a method
public class A {
    public void sayHello() {
        System.out.println("Hello");
    }
}

// Class B delegating A's method
public class B {
    @Delegate
    private A a = new A();

    public static void main(String[] args) {
        B b = new B();
        b.sayHello(); // Calls A.sayHello()
    }
}

This reduces deep inheritance or tight coupling, improving readability and maintainability.

@Cleanup

@Cleanup

automatically manages resources such as input/output streams, ensuring that the close() method is called safely.

Usage example:

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

Lombok wraps the code in a try‑finally block and calls in.close() after execution.

If the resource’s release method is not named close, you can specify it:

@Cleanup("release") MyResource resource = new MyResource();

Lombok will invoke resource.release() in the finally block.

@Singular and @Builder

@Builder

enables fluent, chained object construction, while @Singular makes collection fields easier to populate.

Applying @Singular to a collection generates methods for adding single elements and whole collections, which can be chained with other builder methods.

@Data
@Builder
public class User {
    private String name;
    private int age;
    @Singular
    private List<String> hobbies;
}

// Usage
User user = User.builder()
    .name("Two and a half years of practice")
    .age(28)
    .hobby("Basketball")
    .hobby("Singing")
    .hobbies(Arrays.asList("Dancing", "Other"))
    .build();

The generated collection becomes immutable after build(), ensuring thread safety. You can also clear the collection with clearHobbies() before adding new elements.

Note that if the class extends a parent, @Builder only includes fields of the current class, not those of the superclass.

Conclusion

Although Lombok offers many convenient features, overusing or misusing them can make code hard to understand and maintain. Use these annotations judiciously and consider their impact.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Code Generationspringannotationsdependency-injectionLombok
Java Backend Technology
Written by

Java Backend Technology

Focus on Java-related technologies: SSM, Spring ecosystem, microservices, MySQL, MyCat, clustering, distributed systems, middleware, Linux, networking, multithreading. Occasionally cover DevOps tools like Jenkins, Nexus, Docker, and ELK. Also share technical insights from time to time, committed to Java full-stack development!

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.