UNIT-1 Material
UNIT-1 Material
Spring is a popular open-source Java application development framework created by Rod Johnson. Spring
supports developing any kind of Java application such as standalone applications, web applications,
database-driven applications, and many more.
The basic objective of the framework was to reduce the complexity involved in the development of
enterprise applications. But today Spring is not limited to enterprise application development, many
projects are available under the Spring umbrella to develop different kinds of applications of today’s need
such as cloud-based applications, mobile applications, batch applications, etc. Spring framework helps in
developing a loosely coupled application that is simple, easily testable, reusable, and maintainable.
Spring is a Java-based framework for constructing web and enterprise applications. However, configuring
a Spring application is a tedious job. Even though it provides flexibility in bean configuration with
multiple ways such as XML, annotation, and Java-based configurations, there is no escape from the
configuration. Configuring the Spring features may need more time for developers and may distract the
developers from solving business problems.
Thanks to Spring Team for releasing Spring Boot, one of the topmost innovations in all the existing Spring
Framework. Spring Boot provides a new prototype for developing Spring applications with nominal effort.
Using Spring Boot, you will be able to develop Spring applications with extra agility and capacity to focus
on solving business needs with nominal (or possibly no) configuring.
In this course, we will discuss the core concepts of Spring Framework using Spring Boot that makes it easy
to create a production-grade, stand-alone application that we can just run.
As the course proceeds, we will build this application incrementally to make it for learning the Spring core
concepts with Spring Boot.
InfyTel is built as a three-tier application which consists of
Presentation Layer
Service/Business Layer
Persistence Layer
The service layer of an enterprise application is the layer in which the business logic is implemented. It
In this course Spring Core with Boot, we will see how to develop the Service/Business layer for this
application. Once you have completed this course you can then learn to build the Persistence layer using
Spring JDBC with Spring Boot course and, to build the Rest presentation layer using Spring REST course.
In this course, we will develop the service layer of this application and we will hardcode the persistence
layer.
Why Spring?
Consider our InfyTel application here, we have a CustomerServiceImpl class which implements the
CustomerService interface.
1. packagecom.infy.service;
2.
3. publicinterfaceCustomerService{
4.
5. publicStringfetchCustomer();
6.
7. publicStringcreateCustomer(CustomerDtodto)
8.
9. }
The business logic of InfyTel application is implemented in this class. This class is used to perform
operations like creating a customer, deleting a customer, etc... CustomerServiceImpl class interacts with
CustomerRepository to perform the database related operations.
CustomerServiceImpl.java
1. publicclassCustomerServiceImplimplementsCustomerService{
2.
3. CustomerRepositorycustomerRepository=newCustomerRepositoryImpl();
4.
5. publicStringcreateCustomer(CustomerDtodto){
6. returncustomerRepository.createCustomer(dto);
7.
8. }
9.
10. publicStringfetchCustomer(){
11. returncustomerRepository.fetchCustomer();
12. }
13. }
So we need a more flexible solution where dependencies can be provided externally rather than a
dependent creating its own dependencies. Now let us see such an implementation of CustomerServiceImpl
class.
1. publicclassCustomerServiceImplimplementsCustomerService{
2.
3. privateCustomerRepositorycustomerRepository;
4.
5.
publicCustomerServiceImpl(CustomerRepositorycustomerRepository){
6. this.customerRepository=customerRepository;
7. }
8.
9. publicStringcreateCustomer(CustomerDtodto){
10. returncustomerRepository.createCustomer(dto);
11.
12. }
13.
14. }
15.
This solution is more flexible and easy to test. But at the same time, it is tedious to manually wire together
with the dependencies. Also if you alter the dependencies you may have to change vast amounts of code.
So what is the solution?
We can use a technique called Dependency Injection (DI). It is a technique in which the responsibility of
creating and wiring the dependencies of a dependent class is externalized to the external framework or
library called dependency injection (DI) frameworks. So now the control over the construction and wiring
of an object graph is no longer resides with the dependent classes themselves. This reversal of
responsibilities is known as Inversion of Control(IoC). Dependency injection framework also called IoC
containers.
There are many third-party frameworks that are available for dependency injection such as Spring
Framework, Google Guice, Play Framework, etc. In this course, you will study about Spring Framework.
Besides dependency injection, there are many other advantages of using the Spring Framework which
you will study later in this course.
Note: Inversion of Control (IoC) represents the inversion of application responsibility of the object's
creation, initialization, dependency, and destruction from the application to the third party.
Spring Framework is an open source Java application development framework that supports developing all
types of Java applications such as enterprise applications, web applications, cloud based applications, and
many more.
Java applications developed using Spring are simple, easily testable, reusable, and maintainable.
Spring modules do not have tight coupling on each other, the developer can pick and choose the modules
as per the need for building an enterprise application.
features.
Core: This is the key module of Spring Framework which provides fundamental support on which
all other modules of the framework are dependent.
Bean: This module provides a basic Spring container called BeanFactory.
Context: This module provides one more Spring container called ApplicationContext which
inherits the basic features of the BeanFactory container and also provides additional features to
support enterprise application development.
Spring Expression Language (SpEL): This module is used for querying/manipulating object
values.
AOP (Aspect Oriented Programming) and aspects: These modules help in isolating cross-cutting
functionality from business logic.
We will discuss BeanFactory and ApplicationContext containers in detail later in this course.
Java Database Connectivity (JDBC): It provides an abstract layer to support JDBC calls to
relational databases.
Object Relational Mapping (ORM): It provides integration support for popular ORM(Object-
Relational Mapping) solutions such as Hibernate, JPA, etc.
Transactions: It provides a simple transaction API which abstracts the complexity of underlying
repository specific transaction API's from the application.
Web: This module has a container called web application context which inherits basic features
from ApplicationContext container and adds features to develop web based applications.
Webmvc: It provides the implementation of the MVC(model-view-controller) pattern to
implement the serverside presentation layer and also supports features to implement RESTful Web
Services.
WebFlux: Spring 5.0 introduced a reactive stack with a web framework called Spring WebFlux to
support Reactive programming in Spring's web layer and runs on containers such as Netty,
Undertow, and Servlet 3.1+.
WebSocket: It is used for 2 way communication between client and server in WebSocket based
web applications.
Test: This module provides the required support to test Spring applications using TestNG or
JUnit.
There are few more changes in Spring 5.x with respect to library support and discontinued support, you
can refer to the Spring documentation for additional details.
Spring IoC
Inversion of Control(IoC)
As discussed earlier, usually it is the developer's responsibility to create the dependent application object
using the new operator in an application. Hence any change in the application dependency requires code
change and this results in more complexity as the application grows bigger.
Inversion of Control (IoC) helps in creating a more loosely coupled application. IoC represents the
inversion of the responsibility of the application object's creation, initialization, and destruction from the
application to the third party such as the framework. Now the third party takes care of application object
management and dependencies thereby making an application easy to maintain, test, and reuse.
There are many approaches to implement IoC, Spring Framework provides IoC implementation
using Dependency Injection(DI).
Let us now learn more about Spring IoC through Dependency Injection.
We need not create objects in dependency injection instead describe how objects should be created
through configuration.
DI is a software design pattern that provides better software design to facilitate loose coupling, reuse, and
ease of testing.
Helps to create loosely coupled application architecture facilitating re-usability and easy testing.
Separation of responsibility by keeping code and configuration separately. Hence dependencies
can be easily modified using configuration without changing the code.
Allows to replace actual objects with mock objects for testing, this improves testability by writing
simple JUnit tests that use mock objects.
The core container module of the Spring Framework provides IoC using Dependency Injection.
The Spring container knows which objects to create and when to create through the additional details that
we provide in our application called Configuration Metadata.
Let us understand IoC containers and configuration metadata in detail on the go.
Spring IoC - Containers
BeanFactory:
It is the basic Spring container with features to instantiate, configure and manage the beans.
org.springframework.beans.factory.BeanFactory is the main interface representing a BeanFactory
container.
ApplicationContext:
ApplicationContext is the preferred container for Spring application development. Let us look at more
details on the ApplicationContext container.
BeanFactory Vs ApplicationContext
Let us now understand the differences between BeanFactory and ApplicationContext containers.
BeanFactory ApplicationContext
It does not support annotation based Support annotation based Dependency
Dependency Injection. Injection.
Support enterprise services such as
It does not support enterprise services.
validations, internationalization, etc.
By default, it supports Eager Loading. Beans
By default, it supports Lazy Loading.
are instantiated during load time.
// Loading ApplicationContext and
//Loading BeanFactory
instantiating bean
BeanFactory factory = new
ApplicationContext context = new
AnnotationConfigApplicationContext(SpringC
AnnotationConfigApplicationContext(Spring
onfiguration.class);
Configuration.class);
// Instantiating bean during first access
// Instantiating bean during first access
using getBean()
using getBean()
CustomerServiceImpl service =
CustomerServiceImpl service =
(CustomerServiceImpl)
(CustomerServiceImpl)
factory.getBean("customerService");
context.getBean("customerService");
1. ApplicationContext context
=newAnnotationConfigApplicationContext(SpringConfiguration.class)
;
2. Objectobj=context.getBean("customerService");
You can see a warning message as Resource leak: 'context' is never closed while using the
ApplicationContext type. This is for the reason that you don’t have a close method with BeanFactory or
even ApplicationContext. AbstractApplicationContext is an abstract implementation of the
ApplicationContext interface and it implements Closeable and AutoCloseable interfaces. To close the
application context and destroy all beans in its abstractApplicationContext has a close method that closes
this application context.
1. The traditional way of accessing bean based on bean id with explicit typecast
1. CustomerServiceImpl service
=(CustomerServiceImpl)context.getBean("customerService");
2. Accessing bean based on class type to avoid typecast if there is a unique bean of type in the container
1. CustomerServiceImpl service
=context.getBean(CustomerServiceImpl.class);
2.
3. Accessing bean through bean id and also type to avoid explicit typecast
1. CustomerServiceImpl service
=context.getBean("customerService",CustomerServiceImpl.class);
Configuration Metadata
The Spring configuration metadata consists of definitions of the beans that the container must manage.
Spring allows providing the configuration metadata using :
XML Configuration
Annotation Based configuration
Java Based configuration
The Java-based configuration metadata is provided in the Java class using the following annotations:
@Configuration: The Java configuration class is marked with this annotation. This annotation identifies
this as a configuration class, and it’s expected to contain details on beans that are to be created in the
Spring application context.
@Bean: This annotation is used to declare a bean. The methods of configuration class that creates an
instance of the desired bean are annotated with this annotation. These methods are called by the Spring
containers during bootstrap and the values returned by these methods are treated as Spring beans. By
default, only one bean instance is created for a bean definition by the Spring Container, and that instance is
used by the container for the whole application lifetime.
For example, the SpringConfiguration class can be configured in a Java class using the above annotations
as follows :
1. @Configuration
2.
3. publicclassSpringConfiguration{
4.
5. @Bean
6. publicCustomerServiceImplcustomerService(){
7.
8. returnnewCustomerServiceImpl();
9. }
10. }
11.
By default, the bean name is the same as the name of the method in which the bean is configured. So in the
above code bean name is customerService. If you want to change the bean name then you can either
rename the method or provide a different name with the name attribute as follows:
1. @Configuration
2. publicclassSpringConfiguration{
3.
4. @Bean(name="service")
5. publicCustomerServiceImplcustomerService(){
6.
7. returnnewCustomerServiceImpl();
8. }
9. }
10.
CustomerService.java
1. packagecom.infy.service;
2.
3. publicinterfaceCustomerService{
4. publicStringcreateCustomer();
5. }
6.
CustomerServiceImpl.java
1. packagecom.infy.service;
2.
3. publicclassCustomerServiceImplimplementsCustomerService{
4.
5. publicStringcreateCustomer(){
6. return"Customer is successfully created";
7. }
8.
9. }
10.
SpringConfiguration.java
1. packagecom.infy.util;
2.
3. importorg.springframework.context.annotation.Bean;
4. importorg.springframework.context.annotation.Configuration;
5. importcom.infy.service.CustomerServiceImpl;
6.
7. @Configuration
8.
9. publicclassSpringConfiguration{
10.
11. @Bean(name ="customerService")
12. publicCustomerServiceImplcustomerServiceImpl(){
13. returnnewCustomerServiceImpl();
14. }
15. }
16.
Client.java
1. packagecom.infy;
2.
3. importorg.springframework.context.annotation.AnnotationConfigAppl
icationContext;
4. importorg.springframework.context.support.AbstractApplicationCont
ext;
5. importcom.infy.service.CustomerServiceImpl;
6. importcom.infy.util.SpringConfiguration;
7.
8. publicclassClient{
9. publicstaticvoidmain(String[]args){
10. CustomerServiceImpl service =null;
11. AbstractApplicationContext context
=newAnnotationConfigApplicationContext(SpringConfiguration.class)
;
12. service
=(CustomerServiceImpl)context.getBean("customerService");
13. System.out.println(service.createCustomer());
14. context.close();
15. }
16. }
Output:
Employee Management
We will develop an application using multi-tier architecture as shown below: In this course for all
exercises, we will be focusing on Service layer implementation using Spring core.
Problem Statement:
For the Employee Management scenario, create a Spring Java configuration to maintain Employee details
such as employee id, employee name, and department and perform the following database operations.
1. publicclassEmployeeDTO{
2. privateintempId;
3. privateStringempName;
4. privateString department;
5.
6. }
EmployeeServiceImpl.java
1. publicclassEmployeeServiceImplimplementsEmployeeService{
2. // For this exercise no need to have EmployeeRepository we will
implement repository later in this course
3.
4. // EmployeeRepositoryemployeeDAO = new
EmployeeRepositoryImpl();
5. @Override
6. publicvoidinsert(EmployeeDTO emp){
7. System.out.println("inserted");
8. }
9.
10. publicvoiddelete(intempId){
11. System.out.println("deleted");
12. }
Now, as part of this exercise create a Spring application by introducing the following Spring core concepts.
For the previously discussed InfyTel Customer application, we defined CustomerService bean as shown
below
1. @Bean
2. publicCustomerServicecustomerService(){
3.
4. returnnewCustomerService();
5. }
This is the same as the below Java code wherein an instance is created and initialized with default values
using the default constructor.
1. CustomerServicecustomerService=newCustomerService();
Inversion of Control pattern is achieved through Dependency Injection (DI) in Spring. In Dependency
Injection, the developer need not create the objects but specify how they should be created through
configuration.
Spring container uses one of these two ways to initialize the properties:
Constructor Injection
Constructor Injection - Primitive values
Let us consider the CustomerService class of InfyTel Customer application to understand constructor
injection.
CustomerService class has a count property, let us now modify this class to initialize count property during
bean instantiation using the constructor injection approach.
1. packagecom.infy.service;
2.
3. publicclassCustomerServiceImplimplementsCustomerService{
4. privateint count;
5.
6. publicCustomerServiceImpl(int count){
7. this.count= count;
8. }
9.
10. }
1. @Configuration
2. publicclassSpringConfiguration{
3. @Bean// CustomerService bean definition with bean dependencies
through constructor injection
4. publicCustomerServiceImplcustomerService(){
5. returnnewCustomerServiceImpl(20);
6. }
A parameterized constructor is required in the CustomerService class as we are injecting the values
through the constructor argument.
So far, we learned how to inject primitive values using constructor injection in Spring. Now we will look
into inject object dependencies using Constructor injection.
1. packagecom.infy.service;
2. publicclassCustomerServiceImplimplementsCustomerService{
3. // CustomerServiceImpl needs to contact CustomerRepository, hence
injecting the customerRepository dependency
4.
5. privateCustomerRepositorycustomerRepository;
6. privateint count;
7. publicCustomerServiceImpl(){
8. }
9.
10. publicCustomerServiceImpl(CustomerRepositorycustomerRepos
itory,int count){
11. this.customerRepository=customerRepository;
12. this.count=count;
13. }
14. publicStringfetchCustomer(){
15. returncustomerRepository.fetchCustomer(count);
16. }
17.
18. publicStringcreateCustomer(){
19. returncustomerRepository.createCustomer();
20. }
21.
22. }
Observe in the above code, CustomerRepository property of CustomerSevice class has not been initialized
with any value in the code. This is because Spring dependency is going to be taken care of in the
configuration.
1. packagecom.infy.util;
2.
3. @Configuration
4. publicclassSpringConfiguration{
5.
6. @Bean// customerRepository bean definition
7. publicCustomerRepositorycustomerRepository(){
8. returnnewCustomerRepository();
9. }
10.
11. @Bean// CustomerServic bean definition with bean
dependencies through constructor injection
12. publicCustomerServiceImplcustomerService(){
13.
14.
returnnewCustomerServiceImpl(customerRepository(),20);
15. }
16. }
17.
Setter Injection
Let us now understand Setter Injection in Spring.
In Setter Injection, Spring invokes setter methods of a class to initialize the properties after invoking a
default constructor.
How can we use setter injection to inject values for the primitive type of properties?
Consider the below example to understand setter injection for primitive types.
Following the CustomerServiceImpl class has a count property, let us see how to initialize this property
during bean instantiation using the setter injection approach.
1. packagecom.infy.service;
2. publicclassCustomerServiceImplimplementsCustomerService{
3. privateint count;
4. publicintgetCount(){
5. return count;
6. }
7. publicvoidsetCount(int count){
8. this.count= count;
9. }
10. publicCustomerServiceImpl(){
11. }
12. }
1. packagecom.infy.util;
2. @Configuration
3.
4. publicclassSpringConfiguration{
5.
6.
7. @Bean// CustomerService bean definition using Setter Injection
8. publicCustomerServiceImplcustomerService(){
9.
CustomerServiceImplcustomerService=newCustomerServiceImpl();
10. customerService.setCount(10);
11. returncustomerService;
12. }
13. }
Default constructor and setter methods of respective dependent properties are required in the
CustomerServiceImpl class. For setter injection, Spring internally uses the default constructor to
create a bean and then invokes a setter method of the respective property based on the name
attribute in order to initialize the values.
So far, we learned how to inject primitive values using setter injection in Spring.
1. packagecom.infy.service;
2. publicclassCustomerServiceImplimplementsCustomerService{
3. privateCustomerRepositorycustomerRepository;
4. privateint count;
5.
6. publicCustomerRepositorygetCustomerRepository(){
7. returncustomerRepository;
8. }
9.
10. publicvoidsetCustomerRepository(CustomerRepositorycustome
rRepository){
11. this.customerRepository=customerRepository;
12. }
13.
14. publicintgetCount(){
15. return count;
16. }
17.
18. publicvoidsetCount(int count){
19. this.count= count;
20. }
21.
22. }
23.
1. packagecom.infy.util;
2. @Configuration
3.
4. publicclassSpringConfiguration{
5.
6. @Bean
7. publicCustomerRepositorycustomerRepository(){
8. returnnewCustomerRepository();
9. }
10.
11. @Bean// Setter Injection
12. publicCustomerServiceImplcustomerService(){
13.
CustomerServiceImplcustomerService=newCustomerServiceImpl();
14. customerService.setCount(10);
15.
customerService.setCustomerRepository(customerRepository());
16. returncustomerService;
17. }
18. }
19.
What is AutoScanning
1. @Configuration
2. publicclassSpringConfiguration{
3. @Bean
4. publicCustomerRepositorycustomerRepository(){
5. returnnewCustomerRepository();
6. }
7. @Bean
8. publicCustomerServiceImplcustomerService(){
9.
10. returnnewCustomerServiceImpl();
11. }
12. }
Yes, Spring provides a way to automatically detect the beans to be injected and avoid even the bean
definitions within the Spring configuration file through Auto Scanning. In Auto Scanning, Spring
Framework automatically scans, detects, and instantiates the beans from the specified base package, if
there is no declaration for the beans in the SpringConfiguration class.
1. @Configuration
2. @ComponentScan(basePackages="com.infy")
3. publicclassSpringConfiguration{
4.
5. }
6.
Component scanning
Component scanning isn’t turned on by default, however. You have to annotate the configuration class
with @ComponentScan annotation to enable component scanning as follows:
1. @Configuration
2. @ComponentScan
3. publicclassSpringConfiguration{
4. }
5.
In the above code, Spring will scan the package that contains SpringConfig class and it subpackages for
beans. But if you want to scan a different package or multiple packages then you can specify this with the
basePackages attribute as follows:
1. @Configuration
2. @ComponentScan(basePackages
="com.infy.service,com.infy.repository")
3. publicclassSpringConfiguration{
4. }
5.
Spring uses @ComponentScan annotation for the auto scan feature. It looks for classes with the stereotype
annotations and creates beans for such classes automatically.
Stereotype annotations denote the roles of types or methods at the conceptual level.
Stereotype annotations are @Component, @Service, @Repository, and @Controller annotations.
These annotations are used for auto-detection of beans using @ComponentScan.
The Spring stereotype @Component is the parent stereotype.
The other stereotypes are the specialization of @Component annotation.
Annotation Usage
@Component It indicates the class(POJO class) as a Spring component.
@Service It indicates the Service class(POJO class) in the business layer.
It indicates the Repository class(POJO class in Spring DATA) in the
@Repository
persistence layer.
It indicates the Controller class(POJO class in Spring MVC) in the
@Controller
presentation layer.
1. @Component
2. publicclassCustomerLogging{
3. //rest of the code
4. }
5.
@Service - It is used to define a service layer Spring bean. It is a specialization of the @Component
annotation for the service layer.
1. @Service
2. publicclassCustomerSeviceImplimplementsCustomerService{
3. //rest of the code
4. }
5.
1. @Repository
2. publicclassCustomerRepositoryImplimplementsCustomerRepository{
3. //rest of the code
4. }
5.
1. @Controller
2. publicclassCustomerController{
3. //rest of the code
4. }
5.
By default, the bean names are derived from class names with a lowercase initial character. Therefore,
your above defined beans have the names customerController, customerServiceImpl, and
customerRepositoryImpl. It is also possible to give a specific name with a value attribute in those
annotations as follows:
1. @Repository(value="customerRepository")
2. publicclassCustomerRepositoryImplimplementsCustomerRepository{
3. //rest of the code
4. }
5.
Note: As a best practice, use @Service for the service layer, @Controller for the Presentation layer,
and @Repository for the Persistence layer.