Introduction to Spring.
Inversion of Control
softserve
Agenda
• Inversion of Control
• Spring IoC Container
• Spring Introduction
• Annotation Configuration
• Case Studies
Inversion of Control
Inversion of Control
• Inversion of Control is an abstract principle, a set of guidelines for writing loosely coupled
code.
• Each component of the system should be as isolated from others as possible.
• Dependency Injection (dependency injection) is one of the implementations of this principle
(besides this there is also a Factory Method, Service Locator).
• An IoC container is some kind of library, framework, program, if you like, that will allow you
to simplify and automate your coding.
Dependency Injection
• Inversion of Control (IoC) is a specific set of guidelines for designing and implementing
applications using loose coupling of individual components.
• To follow the principles of Inversion of Control, you must:
• Implement components that are responsible for one specific task;
• The components should be as independent of each other as possible;
• Components should not depend on each other's specific implementation.
• One type of specific implementation of these guidelines is Dependency Injection (DI).
Dependency Injection
• There are several specific Dependency Injection patterns:
• Through the constructor (Constructor injection);
• Through the class property (Setter injection);
• Through the method argument (Method injection).
Implementation without IoC
public class AddOperationService {
private DigitalService digitalService;
public AddOperationService() {
this.digitalService = new DigitalServiceImpl();
}
public String operation(String arg0, String arg1) {
return String.valueOf(digitalService.toInt(arg0)
+ digitalService.toInt(arg1));
}
}
Constructor Injection
public class AddOperationService {
private DigitalService digitalService;
public AddOperationService(DigitalService digitalService) {
this.digitalService = digitalService;
}
public String operation(String arg0, String arg1) {
return String.valueOf(digitalService.toInt(arg0)
+ digitalService.toInt(arg1));
}
}
Setter Injection
public class OrderServiceImpl {
private DigitalService digitalService;
public void setDigitalService(
DigitalService digitalService) {
this.digitalService = digitalService;
}
public String max(String arg0, String arg1) {
return digitalService.toInt(arg0)
> digitalService.toInt(arg1) ? arg0 : arg1;
}
}
Spring IoC Container
Spring IoC Container
• The key element of the Spring Framework is the Spring Container.
• Container creates objects, ties them together, configures and manages them from creation
to destruction.
• Spring Container receives instructions on which objects to instantiate and how to configure
them via metadata.
• Metadata can be obtained in 3 ways:
• XML;
• Java annotations;
• Java code.
Spring IoC Container
• Spring has 2 different kinds of containers:
• Spring BeanFactory Container;
• It is the simplest container, provides basic DI support, interface-based.
• BeanFactory is usually used when resources are limited.
• The most commonly used implementation of the BeanFactory interface is the
XmlBeanFactory.
• The XmlBeanFactory gets the metadata from the XML configuration file and uses it
to create a customized application or system.
• If resources are not very limited, then it is better to use ApplicationContext.
Spring IoC Container
• Spring ApplicationContext Container;
• The container is defined by the
org.springframework.context.ApplicationContext interface.
• ApplicationContext loads the beans, links them together, and configures them.
• ApplicationContext has additional functionality.
<bean id="digitalService" scope="prototype"
class="com.softserve.edu.service.impl.DigitalServiceImpl" />
<bean id="orderService"
class="com.softserve.edu.service.impl.OrderServiceImpl">
<property name="digitalService" ref="digitalService" />
</bean>
Spring Beans
• Beans are objects that are the backbone of the application and are managed by the Spring
IoC container.
• Created using configuration metadata.
• Bean definition contains configuration metadata
• How to create a bean;
• Bean lifecycle information;
• Bean dependencies.
<bean id="resOperation" scope="singleton"
class="com.softserve.edu.service.impl.ResOperationService">
<constructor-arg ref="digitalService" />
</bean>
Spring Beans
• There are properties that define beans.
• class
• This attribute is required and specifies the specific Java application class that will be used
to create the bean.
• name
• The unique identifier for the bean. In case of configuration using an xml file, you can use
the "id" and / or "name" property to identify the bean.
• constructor-arg
• Defines the constructor used for dependency injection.
• properties
• Defines dependency injection properties.
Spring Beans
• scope
• This property determines the scope of the created objects.
• There are five possible values for the scope property
• singleton
• Defines one single bean for each Spring IoC container (default).
• prototype
• Allows to have any number of bean instances.
• request
• One bean instance is created for each HTTP request.
• Only applies to ApplicationContext.
• session
• One bean instance is created for each HTTP session.
• Only applies to ApplicationContext.
• global-session
• One bean instance is created for each global HTTP session.
• Only applies to ApplicationContext.
Spring Beans
• initialization method
• Bean initialization method is defined here.
• destruction method
• The bean destruction method to be used when destroying the container.
• autowiring mode
• Determines the automatic linking mode for dependency injection.
• lazy-initialization mode
• Lazy initialization mode instructs the IoC container to instantiate the bean on the first
request, rather than when the application starts.
<bean id="passenger" scope="prototype“
class="com.softserve.edu.Passenger" />
<bean class="com.softserve.edu.Car">
<lookup-method name="createPassenger“
bean="passenger" /> </bean>
Spring Introduction
Spring Introduction
• The first version was written by Rod Johnson in October 2002.
• The framework was first released under the Apache 2.0 license in June 2003.
• An important component of Spring is the IoC Container.
• DI establishes links between classes, while maintaining their independence from each
other.
• Another key component of Spring is Aspect oriented programming (AOP).
• DI helps you split your application classes into separate modules.
• AOP – helps to decouple cross-cutting concerns from the objects they affect.
• Spring is divided into a number of separate modules.
• Lets you decide which ones to use.
Spring Introduction
• The Spring Framework consists of features organized into about 20 modules. These modules
are grouped into Core Container, Data Access/Integration, Web, AOP (Aspect Oriented
Programming), Instrumentation, Messaging, and Test.
Spring Introduction
• The Core Container includes Beans, Core, Context and SpEL (expression language).
• Beans is responsible for BeanFactory, which is an implementation of the Factory pattern.
• The Core module provides key parts of the framework, including IoC and DI properties.
• Context is built on the basis of Beans and Core and allows you to access any object that is
defined in the settings.
• The key element of the Context module is the ApplicationContext interface.
• The SpEL module provides an expression language for manipulating objects.
Spring Introduction
• The Data Access / Integration container consists of JDBC, ORM, OXM, JMS, and the
Transatcions module.
• JDBC provides an abstract JDBC layer and eliminates the need for the developer to
manually write the monotonous code associated with connecting to the database.
• ORM provides integration with popular ORMs like Hibernate, JDO, JPA, etc.
• The OXM module is responsible for Object / XML communication - XMLBeans, JAXB, etc.
• The JMS (Java Messaging Service) module is responsible for creating, transmitting and
receiving messages.
• Transactions supports transaction management.
Spring Introduction
• The Web layer consists of Web, Web-MVC, Web-Socket, Web-Portlet
• The web module provides functions such as file uploads, etc.
• Web-MVC contains the Spring MVC implementation for web applications.
• Web-Socket provides support for communication between a client and a server using
Web-Sockets in web applications.
• Web-Portlet provides MVC implementation in the portlet framework.
• Spring also includes a lot of other important modules such as AOP, Aspects, Instrumentation,
Messaging, and Test.
• The Test module provides testing using TestNG or the JUnit Framework.
Case Studies.
Euclidean algorithm.
Greatest common divisor (GCD)
Case Studies. DigitalService
public interface DigitalService {
int toInt(String arg0);
}
public class DigitalServiceImpl implements DigitalService {
public int toInt(String arg) {
int result = 0;
try {
result = Integer.valueOf(arg);
} catch (NumberFormatException e) {
throw new IllegalArgumentException("error");
}
return Math.abs(result);
}
}
Case Studies. OperationService
public interface OperationService {
String operation(String arg0, String arg1);
}
public class ResOperationService implements OperationService {
private DigitalService digitalService;
public ResOperationService(DigitalService digitalService) {
this.digitalService = digitalService;
}
public String operation(String arg0, String arg1) {
return String.valueOf(digitalService.toInt(arg0)
% digitalService.toInt(arg1));
}
Case Studies. ConvertServise
public interface ConvertServise {
String validateDigits(String text);
}
public class ConvertServiseImpl implements ConvertServise {
private ConvertServiseImpl() {
patternNotDigitsExist = Pattern.compile(NOT_DIGITS_EXIST);
}
public static ConvertServiseImpl getConvertServise() {
return new ConvertServiseImpl();
}
public String validateDigits(String text) {
result = text.replaceAll("\\D", "");
return result.length() > 0 ? result : "0";
}
}
Case Studies. EuclideanService
public interface EuclideanService {
void setConvertServise(ConvertServise convertServise);
void setOrderService(OrderService orderService);
String calculateGCD(String arg0, String arg1);
}
public class EuclideanServiceImpl implements EuclideanService {
private OperationService operationService;
private ConvertServise convertServise;
private OrderService orderService;
public EuclideanServiceImpl(OperationService
operationService) {
this.operationService = operationService;
}
public void setConvertServise(ConvertServise convertServise){
this.convertServise = convertServise;
}
Case Studies. EuclideanService
public void setOrderService(OrderService orderService) {
this.orderService = orderService;
}
public String calculateGCD(String arg0, String arg1) {
String max = orderService.max(convertServise
.validateDigits(arg0), convertServise.validateDigits(arg1));
String min = orderService.min(convertServise
.validateDigits(arg0), convertServise.validateDigits(arg1));
while (!orderService.isNull(min)) {
String temp = operationService.operation(max, min);
max = orderService.max(min, temp);
min = orderService.min(min, temp);
}
return max;
}
}
Case Studies. Configuration by Java Code
public class Appl {
public static void main(String[] args) {
DigitalService digitalService = new DigitalServiceImpl();
OperationService operationService = new
ResOperationService(digitalService);
OrderService orderService = new OrderServiceImpl();
orderService.setDigitalService(digitalService);
EuclideanService euclideanService = new
EuclideanServiceImpl(operationService);
euclideanService.setConvertServise(ConvertServiseImpl
.getConvertServise());
euclideanService.setOrderService(orderService);
System.out.println("GCD(18, 30) = "
+ euclideanService.calculateGCD("18", "30"));
}
Annotation Configuration
Maven Dependencies
<properties>
<project.build.sourceEncoding>
UTF-8</project.build.sourceEncoding>
<java.version>1.8</java.version>
</properties>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.9.RELEASE</version>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<version>5.6.2</version>
<scope>test</scope>
</dependency>
Annotation Configuration
• Initially, configuration in Spring was available exclusively through an XML file.
• Since Spring 2.5, it is possible to configure using annotations.
• A bean is a Spring-created class object that can be injected as a field value into another
object.
• The @Component annotation tells the framework to turn the class into a bean.
@Component
public class Engine {
// …
}
Annotation Configuration
• In configuration using Java annotations, the key ones are @Configuration, @Component and
@Bean
• @Configuration
• Preceded by a class, it means that the class can be used by the Spring IoC container
as a configuration class for beans.
• @Bean
• The @Bean annotation before the method informs Spring that the object returned
by the given method must be registered as a bean.
@Configuration
public class Config {
@Bean
public Engine createEngine() {
return ...;
}
}
Annotation Configuration
• The difference between @Bean and @Component annotations is that @Bean is more
flexible annotation, we annotate a method with it, not a class
• With @Bean, you can configure beans for those classes whose code you cannot edit, for
example, classes from foreign libraries.
• @Bean can also be used to configure classes generated by factory methods.
• When started, Spring will create an instance of the Engine class. This instance will be a
singleton in our case.
• We can subsequently get it from the application context using the command
Engine engine = context.getBean(Engine.class);
• Bean will be injected into all beans, where we will define it as a dependency.
Annotation Configuration
• If we annotate classes with @Component, then the @ComponentScan annotation must be
added to the configuration file to automatically search for these annotated classes.
• In it, you must specify the name of the package or several packages in which these classes
are located.
• Usually configurations are written in the Config class, but it can be empty.
@ComponentScan("com.softserve.edu.service")
public class Config{
}
• Main Class
ApplicationContext сontext = new
AnnotationConfigApplicationContext(Config.class);
Annotation Configuration
• We can link beans to each other by inserting annotations directly into the Java class.
• There are several types of annotations
• @Required
• Can be applied to setters.
• @Autowired
• Can be applied to setters, regular methods, constructors, and properties.
• @Qualifier
• Used in conjunction with Autowired annotations when binding confusion is possible.
@Component
@Qualifier("SubOperationService")
public class SubOperationService implements OperationService {
@Autowired
private DigitalService digitalService;
Case Studies. Annotation Configuration
@Component
@Scope("prototype")
public class DigitalServiceImpl implements DigitalService {
...
}
@Component
public class OrderServiceImpl implements OrderService {
private DigitalService digitalService;
@Autowired
public void setDigitalService(DigitalService digitalService){
this.digitalService = digitalService;
}
...
}
Case Studies. Annotation Configuration
@Component
@Qualifier("ResOperationService")
public class ResOperationService implements OperationService {
private DigitalService digitalService;
@Autowired
public ResOperationService(DigitalService digitalService) {
this.digitalService = digitalService;
}
}
@Component
@Qualifier("SubOperationService")
public class SubOperationService implements OperationService {
@Autowired
private DigitalService digitalService;
...
}
Case Studies. Annotation Configuration
public class ConvertServiseImpl implements ConvertServise {
...
private ConvertServiseImpl() {
}
public static ConvertServiseImpl getConvertServise() {
return new ConvertServiseImpl();
}
}
@Configuration
@ComponentScan("com.softserve.edu.service")
public class Config {
@Bean //(name = "convertServise")
public ConvertServise createConvertServise() {
return ConvertServiseImpl.getConvertServise();
}
}
Case Studies. Annotation Configuration
• In large applications, dependency injection can lead to ambiguity.
• Several beans satisfy the same dependency.
• Spring has the @Qualifier annotation that allows you to explicitly set the name of the
desired bean.
@Component
@Qualifier("ResOperationService")
public class ResOperationService implements OperationService {
…
}
@Autowired
@Qualifier("ResOperationService")
private OperationService operationService;
Case Studies. Annotation Configuration
• Spring supports multiple annotations for linking dependencies
• @Autowired – Spring-specific annotation, can be applied to fields, constructors, setters;
• @Resource – Annotation from JSR-250 that allows injecting resources from beans to jndi
links;
• @Inject – Developing Dependency Injection for Java. Identical to @Autowired when used
with Spring;
• @Named and behaves like @Qualifier
• @Resource – The bean name is passed by the @Resource annotation parameter (name =
"ResOperationService")
Case Studies. Annotation Configuration
@Component("EuclideanService")
public class EuclideanServiceImpl implements EuclideanService {
private OperationService operationService;
private ConvertServise convertServise;
private OrderService orderService;
@Autowired
public EuclideanServiceImpl(
@Qualifier("ResOperationService")
OperationService operationService) {
this.operationService = operationService;
}
@Autowired
public void setConvertServise(ConvertServise convertServise){
this.convertServise = convertServise;
} …
Case Studies. Annotation Configuration
public class Application {
public static void main(String[] args) {
AnnotationConfigApplicationContext annotationConfigContext =
new AnnotationConfigApplicationContext(Config.class);
EuclideanService euclideanService = (EuclideanService)
annotationConfigContext.getBean("EuclideanService");
EuclideanService euclideanService = annotationConfigContext
.getBean(EuclideanService.class);
annotationConfigContext.close();
System.out.println("GCD(18, 30) = " +
euclideanService.calculateGCD("18", "30"));
}
}
THANKS