Authors Top

If you have a few years of experience in the Java ecosystem, and you’d like to share that with the community, have a look at our Contribution Guidelines.

Spring Top – Temp

Get started with Spring 5 and Spring Boot 2, through the reference Learn Spring course:

>> LEARN SPRING
Lightrun – Third Party Code
announcement - icon

Flakiness in REST requests is a common issue. A request can get a 200 OK in one scenario and a 409 next time. Sometimes a request can even succeed and fail intermittently on the same exact request. In short, working over HTTP can be a bit of a mess without solid tooling.

Also, while it’s easy enough to debug these issues locally when developing the application, we’re talking about production here - we can’t afford the downtime while you’re stepping in and out of code. Uptime is kind of the whole point.

With Lightrun, you can get the same level of access you get with a local debugger or profiler - no downtime required. You can add logs, metrics, and snapshots (think breakpoints, but without stopping the running service), in a safe and read-only manner - without redeploying, restarting, or even stopping the running service. Performance and security are maintained throughout the process.

Learn how to debug a live REST API (built with Spring, of course), using Lightrun, in this 5-minute tutorial:

>> Debugging REST Requests in Spring-Based applications using the Lightrun Platform

1. Introduction

Arguably one of the most important development principles of modern software design is Dependency Injection (DI), which quite naturally flows out of another critically important principle: Modularity.

This quick tutorial will explore a specific type of DI technique within Spring called Constructor-Based Dependency Injection, which simply put, means that we pass the required components into a class at the time of instantiation.

To get started, we need to import the spring-context dependency in our pom.xml:

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.2.8.RELEASE</version>
</dependency>

Then we need to set up a Configuration file. This file can be either a POJO or an XML file, based on preference.

Further reading:

Intro to Inversion of Control and Dependency Injection with Spring

A quick introduction to the concepts of Inversion of Control and Dependency Injection, followed by a simple demonstration using the Spring Framework

Top Spring Framework Interview Questions

A quick discussion of common questions about the Spring Framework that might come up during a job interview.

Wiring in Spring: @Autowired, @Resource and @Inject

This article will compare and contrast the use of annotations related to dependency injection, namely the @Resource, @Inject, and @Autowired annotations.

2. Annotation Based Configuration

Java configuration files look similar to Java objects with some additional annotations:

@Configuration
@ComponentScan("com.baeldung.constructordi")
public class Config {

    @Bean
    public Engine engine() {
        return new Engine("v8", 5);
    }

    @Bean
    public Transmission transmission() {
        return new Transmission("sliding");
    }
}

Here we're using annotations to notify Spring runtime that this class provides bean definitions (@Bean annotation), and that the package com.baeldung.spring needs to perform a context scan for additional beans. Next, we define a Car class:

@Component
public class Car {

    @Autowired
    public Car(Engine engine, Transmission transmission) {
        this.engine = engine;
        this.transmission = transmission;
    }
}

Spring will encounter our Car class while doing a package scan, and will initialize its instance by calling the @Autowired annotated constructor.

By calling the @Bean annotated methods of the Config class, we will obtain instances of Engine and Transmission. Finally, we need to bootstrap an ApplicationContext using our POJO configuration:

ApplicationContext context = new AnnotationConfigApplicationContext(Config.class);
Car car = context.getBean(Car.class);

3. Implicit Constructor Injection

As of Spring 4.3, classes with a single constructor can omit the @Autowired annotation. This is a nice little bit of convenience and boilerplate removal.

On top of that, also starting with 4.3, we can leverage the constructor-based injection in @Configuration annotated classes. In addition, if such a class has only one constructor, we can omit the @Autowired annotation as well.

4. XML Based Configuration

Another way to configure Spring runtime with constructor-based dependency injection is to use an XML configuration file:

<bean id="toyota" class="com.baeldung.constructordi.domain.Car">
    <constructor-arg index="0" ref="engine"/>
    <constructor-arg index="1" ref="transmission"/>
</bean>

<bean id="engine" class="com.baeldung.constructordi.domain.Engine">
    <constructor-arg index="0" value="v4"/>
    <constructor-arg index="1" value="2"/>
</bean>

<bean id="transmission" class="com.baeldung.constructordi.domain.Transmission">
    <constructor-arg value="sliding"/>
</bean>

Note that constructor-arg can accept a literal value or a reference to another bean, and that an optional explicit index and type can be provided. We can use Type and index attributes to resolve ambiguity (for example if a constructor takes multiple arguments of the same type).

name attribute could also be used for xml to java variable matching, but then your code must be compiled with debug flag on.

In this case, we need to bootstrap our Spring application context using ClassPathXmlApplicationContext:

ApplicationContext context = new ClassPathXmlApplicationContext("baeldung.xml");
Car car = context.getBean(Car.class);

5. Pros and Cons

Constructor injection has a few advantages compared to field injection.

The first benefit is testability. Suppose we're going to unit test a Spring bean that uses field injection:

public class UserService {
    
    @Autowired 
    private UserRepository userRepository;
}

During the construction of a UserService instance, we can't initialize the userRepository state. The only way to achieve this is through the Reflection API, which completely breaks encapsulation. Also, the resulting code will be less safe compared to a simple constructor call.

Additionally, with field injection, we can't enforce class-level invariants, so it's possible to have a UserService instance without a properly initialized userRepository. Therefore, we may experience random NullPointerExceptions here and there. Also, with constructor injection, it's easier to build immutable components.

Moreover, using constructors to create object instances is more natural from the OOP standpoint.

On the other hand, the main disadvantage of constructor injection is its verbosity, especially when a bean has a handful of dependencies. Sometimes it can be a blessing in disguise, as we may try harder to keep the number of dependencies minimal.

6. Conclusion

This brief article has showcased the basics of two distinct ways to use Constructor-Based Dependency Injection using the Spring framework.

The full implementation of this article can be found over on GitHub.

Spring bottom

Get started with Spring 5 and Spring Boot 2, through the Learn Spring course:

>> THE COURSE
Generic footer banner
Comments are closed on this article!