Constructor Injection in Spring with Lombok

1. Introduction

Lombok is an extremely useful library overcoming boilerplate code. If you are not familiar with it yet, I highly recommend taking a look at the previous tutorial – Introduction to Project Lombok.

In this article, we’ll demonstrate its usability when combined with Spring’s Constructor-Based Dependency Injection.

2. Constructor-Based Dependency Injection

A good way to wire dependencies in Spring using constructor-based Dependency Injection. This approach forces us to explicitly pass component’s dependencies to a constructor.

As opposed to Field-Based Dependency Injection, it also provides a number of advantages:

  • no need to create a test-specific configuration component – dependencies are injected explicitly in a constructor
  • consistent design – all required dependencies are emphasized and looked after by constructor’s definition
  • simple unit tests – reduced Spring Framework’s overhead
  • reclaimed freedom of using final keywords

However, due to the need for writing a constructor, it uses to lead to a significantly larger code base. Consider the two examples of GreetingService and FarewellService:

@Component
public class GreetingService {

    @Autowired
    private Translator translator;

    public String produce() {
        return translator.translate("hello");
    }
}
@Component
public class FarewellService {

    private final Translator translator;

    public FarewellService(Translator translator) {
        this.translator = translator;
    }

    public String produce() {
        return translator.translate("bye");
    }
}

Basically, both of the components do the same thing – they call a configurable Translator with a task-specific word.

The second variation, though, is much more obfuscated because of the constructor’s boilerplate which doesn’t really bring any value to the code.

In the newest Spring release, it’s constructor does not need to be annotated with @Autowired annotation.

3. Constructor Injection With Lombok

With Lombok, it’s possible to generate a constructor for either all class’s fields (with @AllArgsConstructor) or all final class’s fields (with @RequiredArgsConstructor). Moreover, if you still need an empty constructor, you can append an additional @NoArgsConstructor annotation.

Let’s create a third component, analogous to the previous two:

@Component
@RequiredArgsConstructor
public class ThankingService {

    private final Translator translator;

    public String produce() {
        return translator.translate("thank you");
    }
}

The above annotation will cause Lombok to generate a constructor for us:

@Component
public class ThankingService {

    private final Translator translator;

    public String thank() {
        return translator.translate("thank you");
    }

    /* Generated by Lombok */
    public ThankingService(Translator translator) {
        this.translator = translator;
    }
}

4. Multiple Constructors

A constructor doesn’t have to be annotated as long as there is only one in a component and Spring can unambiguously choose it as the right one to instantiate a new object. Once there are more, you also need to annotate the one that is to be used by IoC container.

Consider the ApologizeService example:

@Component
@RequiredArgsConstructor
public class ApologizeService {

    private final Translator translator;
    private final String message;

    @Autowired
    public ApologizeService(Translator translator) {
        this(translator, "sorry");
    }

    public String produce() {
        return translator.translate(message);
    }
}

The above component is optionally configurable with the message field which cannot change after the component is created (hence the lack of a setter). It thus required us to provide two constructors – one with full configuration and the other with an implicit, default value of the message.

Unless one of the constructors is annotated with either @Autowired@Inject or @Resource, Spring will throw an error:

Failed to instantiate [...]: No default constructor found;

If we wanted to annotate the Lombok-generated constructor, we would have to pass the annotation with an onConstructor parameter of the @AllArgsConstructor:

@Component
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class ApologizeService {
    // ...
}

The onConstructor parameter accepts an array of annotations (or a single annotation like in this specific example) that are to be put on a generated constructor. The double underscore idiom has been introduced because of the backward compatibility issues. According to the documentation:

The reason of the weird syntax is to make this feature work in javac 7 compilers; the @__[/code] type is an annotation reference to the annotation type __[/code] (double underscore) which doesn’t actually exist; this makes javac 7 delay aborting the compilation process due to an error because it is possible an annotation processor will later create the __[/code] type.

5. Summary

In this tutorial, we showed that there is no need to favor field-based DI over constructor-based DI in terms of increased boilerplate code.

Thanks to Lombok, it’s possible to automate common code generation without a performance impact on runtime, abbreviating long, obscuring code to the use of a single-line annotation.

The code used during the tutorial is available over on GitHub.

Related posts:

Primitive Type Streams in Java 8
Java Program to Implement Johnson’s Algorithm
Java Program to Implement Ford–Fulkerson Algorithm
Java Program to Solve a Matching Problem for a Given Specific Case
Guide to Escaping Characters in Java RegExps
Vòng lặp for, while, do-while trong Java
Query Entities by Dates and Times with Spring Data JPA
Registration – Password Strength and Rules
How to Count Duplicate Elements in Arraylist
How to Round a Number to N Decimal Places in Java
A Guide to WatchService in Java NIO2
Java Convenience Factory Methods for Collections
Java Program to Test Using DFS Whether a Directed Graph is Strongly Connected or Not
Semaphore trong Java
Create Java Applet to Simulate Any Sorting Technique
Java – Random Long, Float, Integer and Double
Java Program for Topological Sorting in Graphs
Java Program to Find the Edge Connectivity of a Graph
HashSet trong Java hoạt động như thế nào?
Giới thiệu Aspect Oriented Programming (AOP)
Hướng dẫn Java Design Pattern – Strategy
Ways to Iterate Over a List in Java
Comparing Dates in Java
Java Program to Implement the Alexander Bogomolny’s UnOrdered Permutation Algorithm for Elements Fro...
The SpringJUnitConfig and SpringJUnitWebConfig Annotations in Spring 5
Java Program to Find the Minimum value of Binary Search Tree
Java Program to Search for an Element in a Binary Search Tree
Tránh lỗi NullPointerException trong Java như thế nào?
Java – Convert File to InputStream
Các nguyên lý thiết kế hướng đối tượng – SOLID
So sánh HashMap và Hashtable trong Java
Java Program to Implement Hash Tree