Dependency injection in Spring Boot

 

Getting Started in Spring Boot, Part 9 Dependency Injection in Spring Boot

Dependency Injection is one of Spring’s fundamental concepts. Set methods already allowed this in the very first framework version. Later constructor and field injection were added as alternatives. But which type do you use when?

Company about the topic

Everyone talks about vaccinating, and so do we: the inoculation of objects known as dependency Injection is one of Spring's basic concepts.Everyone talks about vaccinating, and so do we: the inoculation of objects known as dependency Injection is one of Spring’s basic concepts.

Objects in Java (and other object-oriented programming languages) communicate with other objects to accomplish the task assigned to them. Programs are therefore networks of interacting objects. The easiest way to get instances of helper classes is to create them yourself with the new operator:

public class VeryImportantService {   private DatabasePersister databasePersister;   public VeryImportantService() {
this.databasePersister = new DatabasePersister();
}
}

This is easy and fast, but has several disadvantages. By the line this.data base persister = new data base persister(); is a fixed dependence to exactly the type Data base persister put in place. Data base persister not more can be easily against a different type (file system, persister, cloud persister or similar) to replace.

This is different when using Dependency injection (DI). In this case, the object does not instantiate the required class itself, but is injected with the dependency on a DI container at the start of the application. The container, in our case Spring, is therefore now responsible for creating the required objects.

For this purpose, Spring searches the available beans in the container for suitable types. Because of this transfer of responsibility to the framework, it is also referred to as Inversion of Control (IOC). The advantage: the fixed dependence is eliminated.

If the dependency is even specified in the form of an interface, here for example Persister, instead of a specific class, different types can even be injected depending on the configuration. This allows not only different implementations of a type, but also test classes (mocks and stubs) to be injected.

Dependency injection is one of the most important patterns at all and can be realized in Spring – as mentioned at the beginning – in three different ways.

Constructor-Injection

During constructor injection, the required object is listed as an argument in the constructor and is automatically injected by the container:

@Component
public class VeryImportantService {
   // Abhängigkeit zu Persister
private Persister persister;
   // Konstruktor, über den der Container ein Persister-Objekt injiziert
@Autowired
public VeryImportantService(Persister persister) {
this.persister = persister;
}
   // Logik, die den injizierten Persister benutzt
// ...
}

Since Spring 4.3, the Annotation can @ Autowired also be omitted if there is only one constructor. With multiple constructors, the @ Autowired defines in which is injected.

Setter-Injection

The Setter injection works similarly, the Spring Container calls the Setter methods after instantiating the bean:

class VeryImportantService {   // Abhängigkeit zu Persister
private Persister persister;
   @Autowired
// Setter, über den der Container ein Persister-Objekt injiziert
public void setPersister(Persister persister) {
this.persister = persister;
}
   // Logik, die den injizierten Persister benutzt
// ...
}

With the help of @Required Annotation if necessary, you can make sure that the property really exists and is not about zero.

Field Injection

The third option is field injection. It looks very clean and requires the least Code. Only the member variable with @ Autowired annotate. The injection takes place after the instantiation of the class:

class VeryImportantService {   @Autowired
private Persister persister;
   // Logik, die den injizierten Persister benutzt
// ...
}

The agony of choice

The different injection options have all their advantages and disadvantages and these are discussed in the net lively, for example here in the Spring blog. In practice, the following three rules have proven themselves:

  • 1. For all of the required dependencies, we are using Constructor Injection. The object is not created at all if the dependencies are not present and a further check can be omitted.
  • 2.For optional properties, the setter injection is used, especially if meaningful default values can be set in the event that no object is present. Otherwise, you have to check everywhere that the object is not zero before you address it.
  • 3. The field injection is best not used at all. The problem with this variant is that a new member variable can be added very easily. Too easy. So classes with many dependencies arise very quickly, which grow out of their actual responsibility.

In constructor injection, constructors with more than five arguments quickly catch the eye, or rather pull as a bad smell (does the class possibly have to be divided?) in the nose. Newer frameworks like Angular therefore no longer offer the Field variant. However, due to its clarity, it is relatively often used in books or blog articles.

Collection-Injection

Finally, it is also worth mentioning the possibility of injecting so-called collections, i.e. lists, sets or maps. Thanks to typed collections, it is possible to precisely describe the type of object to be injected. In the following example, the container searches for a map that contains strings as keys and floats as values.

public class VeryImportantService {   private Map<String, Float> accounts;   public void setAccounts(Map<String, Float> accounts) {
this.accounts = accounts;
}
}

Related but not the same is injecting individually configured beans as collections. In the following configuration, three different beans are configured, all of which implement the Persister interface:

@Configuration
public class PersisterConfig {
   @Bean
public Persister databasePersister() {
return new DatabasePersister();
}
   @Bean
public Persister filesystemPersistery() {
return new FilesystemPersister();
}
   @Bean
public Persister cloudPersister() {
return new CloudPersister();
}
}

All three beans at once can now be injected into a list of the Persister type, for example:

@Service
public class PersisterService {
   @Autowired
List<Persister> persisters;   // ...
}

This ends the big vaccination special. In the next part of the series we take a look into the toolbox again and look at the Lombok project. See you then!

(ID:47242676)

Ready to see us in action:

More To Explore

IWanta.tech
Logo
Enable registration in settings - general
Have any project in mind?

Contact us:

small_c_popup.png