Dependency injection
Spring Boot takes an opinionated view of the Spring platform and third-party libraries. At the heart of the Spring platform lies the Spring framework and its implementation of the inversion of Control principle, which Rod Johnson, the creator of Spring, popularized in his reference book Expert One-on-One J2EE™ Design and Development, published in 2002.
Let’s illustrate how dependency injection is done starting from Wikipedia’s example.
1public class Client {
2 private Service service;
3
4 // The dependency is injected through a constructor.
5 Client(final Service service) {
6 if (service == null) {
7 throw new IllegalArgumentException("service must not be null");
8 }
9 this.service = service;
10 }
11}Without Spring we would have to write something like this:
1Service service = new ExampleService();
2Client client = new Client(service);One component in our application has to explicitly inject an instance of service into the client.
With Spring we would likely use a more decoupled approach.
First, we would describe our objects, or beans, in isolation, in @Configuration-annotated classes.
1import org.springframework.context.annotation.Bean;
2import org.springframework.context.annotation.Configuration;
3
4@Configuration
5public class MyConfiguration {
6
7 @Bean
8 public Service service() {
9 return new ExampleService();
10 }
11
12 @Bean
13 public Client client(Service service) {
14 return new Client(service);
15 }
16
17}We would then query the context for a bean of the required type.
1import org.springframework.context.ApplicationContext;
2import org.springframework.context.annotation.AnnotationConfigApplicationContext;
3
4public class Main {
5
6 public static void main(String[] args) {
7 ApplicationContext context = new AnnotationConfigApplicationContext(SomeConfiguration.class);
8 Client client = context.getBean(Client.class);
9 }
10
11}Configuration classes act as bean factories. The advantage is that if the construction of a particular component changes, only one place needs to be updated.
Spring Boot already creates an ApplicationContext.
There is no need to instantiate one.
Another way to configure beans is to directly annotate classes with a stereotype annotation, such as @Component, @Service, or @Repository.
We have already seen such an annotation in action with @RestController in the previous section.