In this post, we will focus on configuring Spring beans in a Spring-boot environment using Java configuration and constructor injection. This example should be valid for Spring version 4.3 and later. Let us start by discussing a couple of basic concepts.

If you want to improve your Spring boot skills, then I would suggest that you check out the book “Learning Spring Boot 2.0 – Second Edition: Simplify the development of lightning fast applications based on microservices and reactive programming”(click to check current price on Amazon) by Greg Turnquist. The book covers Spring boot basics and provides an overview of integrating important technologies such as AMQP messaging and REST into your application.

What is constructor injection?

Constructor injection is the process of injecting Spring dependencies into a Spring bean using the bean’s constructor. This differs from field injection where a dependency is simply injected using the @Autowired annotation directly on the field. Declaring a bean dependency via constructor injection usually looks as follows:

While it may seem that it is extra work to do than field injection, constructor injection helps to spot Spring beans that have too many dependencies. So if it takes you half an hour to write the bean’s constructor, it may be time to split the bean’s functionalities into multiple smaller services.

Java bean configuration

Spring beans can be declared either inside an XML configuration or a Java configuration. Java configuration has been gaining popularity in recent years over XML configuration as it provides the power of Java into your configuration. In XML, only declarations and configurations can be written, while in Java, various factors and algorithms can run while configuring the Spring beans, giving a more powerful mechanism to configure beans. For example, one could add a condition to choose a specific implementation of bean depending on a database value on system startup.

Now, let us start with our example configuration. Our configuration consists of 2 beans. First is a “CalculatorService”. The second bean is an “AccountingService”. The Accounting service has a dependency on the Calculator service. We will use an interface / class impl pattern for this example. Let us start first with our Calculator service and implementation:

and here is the implementation:

Notice that we do not need any Spring annotations in neither the interface nor the bean implementation. This is because the bean will be added to the application context via the Java configuration. Let us move on to the Accounting service.

And the implementation:

Notice here that we did not need to add the @Autowired annotation on neither the constructor nor the field. As we perform constructor injection, we do not need to add the @Autowired annotation on the field. Since we use Spring 5.1 in our example, we also do not need to add the @Autowired annotation to the constructor. Let us see how this all comes together in the Java configuration class:

Let us discuss the two declarations. The first declaration starts up our CalculationService bean. In the bean declaration, we simply use the default constructor to start up the bean. The second declaration uses the constructor we defined in the AccountingServiceBean. Since we need an instance of the Calculation service to start up our Accounting bean, we declare the CalculatorService as a dependency in the bean definition method signature accountingService(CalculationService calculationService){…

Let us test our Spring configuration in a simple test class. If our configuration is correct, we should get the result of the addition of two numbers. In order to import our Java configuration, we should declare it using the @Import annotation in our test class.

Since we annotated our test with the @SpringBootTest annotation, our test will attempt to start a full application context, with the configuration classes that are imported using the @Import annotation. Here, we imported the AccountingSpringConfig class that we just defined. When we run the test, we will get the following log statements:

As you can see, our AccountingService bean has been successfully autowired along with its dependency and we were able to use the CalculatorService in order to perform an addition.

Thank you for reading our article. We hope you enjoyed. If you found this content useful, then please help us out by following us on Twitter using the follow button below 😉