Spring in a nutshell

The core technology of the Spring Framework is known as Inversion of Control (IoC), which is the process of instantiating objects outside the class in which these objects are actually used. These objects are known as beans or components in the Spring jargon and are created as singleton objects by default. The entity in charge of the creation of beans is known as the Spring IoC container. This is achieved by Dependency Injection (DI), which is the process of providing dependencies of one object instead of constructing them itself.

IoC and DI are often used interchangeably. Nevertheless, as depicted in the paragraph earlier, these concepts are not exactly the same (IoC is achieved through DI).

As depicted in the next part of this section, Spring is a modular framework. The core functionally of Spring (that is, IoC) is provided in the spring-context module. This module provides the ability of creating application context, that is, the Spring’s DI container. There are many different ways to define application contexts in Spring. Two of the most significant types are the following:

  • AnnotationConfigApplicationContext: Application context, which accepts annotated classes to identify the Spring beans to be executed in the container. In this type of context, beans are identified by annotating plain classes with the annotation @Component. It is not the only one to declare a class as a Spring bean. There are further stereotypes annotations: @Controller (stereotype for presentation layer, used in the web module, MVC), @Repository (stereotype for the persistence layer, used in the data access module, called Spring Data), and @Service (used in the service layer). These three annotations are used to separate the layers of an application. Finally, classes annotated with @Configuration allows to define Spring beans by annotating methods with @Bean (the object returned by these methods will be Spring beans living in the container):
Spring stereotypes used to define beans
  • ClassPathXmlApplicationContext: Application context, which accepts bean definitions declared in an XML file located in the project classpath.
The annotation-based context configuration was introduced in Spring 2.5. The Spring IoC container is totally decoupled from the format in which configuration metadata (that is, bean definition) is actually written. Nowadays many developers chose annotation-based configuration rather than XML based. For this reason, in this book, we are going to use only annotation-based context configuration in the examples.

Let’s see a simple example. First of all, we need to include the spring-context dependency in our project. For example, as a Maven dependency:

<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring-context.version}</version>
</dependency>

Then, we create an executable Java class (that is, with a main method). Notice that in this class there is one annotation at class level: @ComponentScan. This is a very important annotation in Spring, since it allows to declare the package in which Spring will look for beans definition in the form of annotations. If specific packages are not defined (just like in the example), scanning will occur from the package of the class that declares this annotation (in the example the package io.github.bonigarcia). In the body of the main method, we create the Spring application context with AnnotationConfigApplicationContext. From that context, we get the Spring component whose class is MessageComponent, and we write the result of its getMessage() method on the standard output:

package io.github.bonigarcia;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;

@ComponentScan
public class MySpringApplication {

public static void main(String[] args) {
try (AnnotationConfigApplicationContext context = new
AnnotationConfigApplicationContext(
MySpringApplication.class)) {
MessageComponent messageComponent = context
.getBean(MessageComponent.class);
System.out.println(messageComponent.getMessage());
}
}

}

The bean MessageComponent is defined in the following class. Notice that it is declared as the Spring component simply using the annotation @Component at class level. Then, in this example, we are injecting another Spring component called MessageService using the class constructor:

package io.github.bonigarcia;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
public class MessageComponent {

private MessageService messageService;

public MessageComponent(MessageService messageService) {
this.messageService = messageService;
}

public String getMessage() {
return messageService.getMessage();
}

}

At this point, it is worth reviewing the different manners to carry out dependency injection of Spring components:

  1. Field injection: The injected component is a class field annotated with @Autowired, just like the example before. As a benefit, this kind of injection removes clutter code such as setter methods or constructor parameters.
  2. Setter injection: The injected component is declared as a field in the class, and then a setter for this field is created and annotated with @Autowired.
  1. Constructor injection: The dependency is injected in the class constructor, which is annotated with @Autowired (3-a in the diagram here). This is the way shown in the example earlier. As of Spring 4.3, it is not required anymore to annotate the constructor with @Autowired to carry out the injection (3-b).
The latest way of injection (3-b) was several benefits, such as the promotion of testability without the need of reflection mechanism (implemented, for example, by mocking library). In addition, it can make developers to think over the design of the class, since many injected dependencies suppose many constructor parameters, and this should be avoided (God object anti-pattern).
Different ways of dependency injection (Autowired) in Spring

The last component in our example is named MessageService. Note that is also a Spring component, this time annotated with @Service to remark its service nature (from a functional perspective, it would be the same than annotating the class with @Component):

package io.github.bonigarcia;

import org.springframework.stereotype.Service;

@Service
public class MessageService {

public String getMessage() {
return "Hello world!";
}

}

Now, if we execute the main class of this example (called MySpringApplication, see the source code here), we create an annotation-based application context with a try with resources (this way the application context will be closed at the end). The Spring IoC container will create two beans: MessageService and MessageComponet. Using the application context, we seek the bean MessageComponet and invoke its method getMessage, which is finally written in the standard output:

package io.github.bonigarcia;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.ComponentScan;

@ComponentScan
public class MySpringApplication {

public static void main(String[] args) {
try (AnnotationConfigApplicationContext context = new
AnnotationConfigApplicationContext(
MySpringApplication.class)) {
MessageComponent messageComponent = context
.getBean(MessageComponent.class);
System.out.println(messageComponent.getMessage());
}
}

}
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
52.15.176.80