Hey there, We are Blossom Themes! We are trying to provide you the new way to look and use the blogger templates. Our designers are working hard and pushing the boundaries of possibilities to widen the horizon of the regular templates and provide high quality blogger templates to all hardworking bloggers!
Spring is a popular open source Java application development framework created by Rod Johnson. Spring supports developing any kind of Java applications 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 Spring umbrella to develop different kind of applications of today’s need such as cloud based applications, mobile applications, batch application etc.
Spring framework helps in developing a loosely coupled application which is simple, easily testable, reusable and maintainable.
The basic Spring Framework is organized as loosely coupled modules, development team can choose modules based on the need. The fundamental module of framework is the core container providing core functionalities on which all other Spring modules/projects are based.
In this course, we will be using a simple Report Generation application scenario for learning the Spring core concepts.
Report Generation application is basically designed to generate reports in different formats such as PDF and HTML.
The application architecture is as shown below:
Application description
ReportGenerator: Interface with generateReport() method for report generation.
HTMLReportGenerator: Class for implementing ReportGenerator interface to generate report in Html format.
PDFReportGenerator:Class for implementing the ReportGenerator interface to generate the report in Pdf format.
ReportService: Class to provide report generation service to the client by using HTMLReportGenerator/PDFReportGenerator class.
Client: Class with client code to access report generation service to generate the report in PDF/HTML format.
why spring?
Let us consider an application scenario of generating a report in different formats such as PDF/HTML using Java.
Consider the following code:
ReportGenerator.java --> Interface
package com.infosys.demo;
publicinterfaceReportGenerator{
publicString generateReport(int recordsPerPage);
}
HTMLReportGenerator.java --> Implementation class for generating HTML reports
Client.java --> Client code to access the report service
package com.infosys.demo;
publicclassClient{
publicstaticvoid main(String[] args){
ReportService service =newReportService();
service.generateReport();
}
}
In the above code,
ReportService is responsible for instantiating dependent HTMLReportGenerator instance using the new operator to generate the report in an appropriate format.
If the pdf report needs to be generated then Line1 of ReportService has to be modifiedbecause this application is tightly coupled.
Refer complete source code of Report Generation application implemented using Java (demo1-report-generation-java-application) from downloaded demos.
Are we developing a loosely coupled application in the above scenario?
Answer is No, because code change is required for any changes to the dependencies. In a traditional way, it is the application developer responsibility to manage the application object life cycle along with its dependencies. Hence the application code is not completely loosely coupled which results in more complexity as the application grows bigger.
Is it possible to make an application more loosely coupled ?
Yes, this can be done by moving the application object life cycle management responsibility to the third party such as a framework. Inversion of control(IoC) is the approach used to achieve this, there are different implementations for IoC and Spring Framework provides IoC implementation using Dependency Injection(DI).
Spring's Dependency Injection features makes an application loosely coupled by moving object dependencies away from the application to the Spring container. Now the container manages objects and its dependencies allowing developer to focus more on application code.
You will be learning Dependency Injection.
Note:Inversion of Control (IoC) represents the inversion of application responsibility of object's creation, initialization, dependency and destruction from the application to the third party.
Spring Framework
Spring Framework is an open source Java application development framework which 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 does not have tight coupling on each other, developer can pick and choose the modules as per the need for building an enterprise application.
Main features of the Spring Framework.
pring Feature
Description
Light Weight
Spring JARs are relatively small.
A basic Spring framework would be lesser than 10MB.
It can be deployed in Tomcat and they do not require heavy-weight application servers.
Non-Invasive
The application is developed using POJOs.
No need to extend /implement any pre-defined classes.
Loosely Coupled
Spring features like Dependency Injection and Aspect Oriented Programming help in loosely coupled code.
Inversion of Control(IoC)
IoC takes care of the application object's life cycle along with their dependencies.
Spring Container
Spring Container takes care of object creation, initialization, and managing object dependencies.
Aspect Oriented Programming(AOP)
Promotes separation of supporting functions(concerns) such as logging, transaction, and security from the core business logic of the application.
Invasive feature mandates the user to implement/extend framework-specific classes/interfaces making the application tightly coupled. However, the Non-Invasive feature of Spring prevents the user to extend/implement any class/interface for Spring support. Spring Framework - Modules features
Spring Framework 5.x has the following key module groups:
Core Container: These are core modules that provide key features of the Spring framework.
Data Access/Integration: These modules support JDBC and ORM data access approaches in Spring applications.
Web: These modules provide support to implement web applications.
Others: Spring also provides few other modules such as the Test for testing Spring applications.
Core Container of Spring framework provides the Spring IoC container and Dependency Injection features.
Spring Framework - Modules
Spring Modules - Core Container
Core container has the following modules:
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 value.
AOP (Aspect Oriented Programming) and aspects: These modules help in isolating cross-cutting functionality from business logic.
Spring Modules - Data Access/Integration
The Data Access/Integration module of Spring provides different data access approaches.
The following modules support Data Access/Integration.
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 simple transaction API which abstracts the complexity of underlying repository specific transaction API's from the application.
Spring Modules - Web
Spring Framework Web module provides basic support for web application development. Web module has a web application context that is built on the application context of the core container. Web module provides complete Model-View-Controller(MVC) implementation to develop a presentation tier of the application and also support a simpler way to implement RESTful web services.
Spring Framework provides the following modules to support web application development.
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 server side presentation layer and also support 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.
Spring Framework has few additional modules, test module is one of the most commonly used one for testing Spring applications.
Test: This module provides required support to test Spring applications using TestNG or JUnits
The current version of Spring Framework is 5.x, the framework has been enhanced with new features keeping core concepts same as Spring 4.x.
At a high level, the new features of Spring Framework 5.x are:
JDK baseline update
Core framework revision
Reactive Programming Model: Introduces a new non-blocking web framework calledSpring WebFlux
Functional programming using Kotlin language support
Testing improvements by supporting integration with JUnit5
Let us look at Spring core relevant changes in detail:
JDK baseline update
The entire Spring framework 5.x codebase runs on Java 8 and designed to work with Java 9. Therefore, Java 8 is the minimum requirement to work on Spring Framework 5.x
Core framework revision
The core Spring Framework 5.x has been revised, one of the main changes is Spring comes with its own commons-logging through spring-jcl jarinstead of standard Commons Logging.
There are few more changes in Spring 5.x with respect to library support and discontinued support, you can referNew in Spring Framework 5.x for additional details. Note:
The development team needs to implement a Spring application with the data access layer to perform the required database operations
Core
ORM
An online shopping web application has to be developed with the data access layer to get item details
Web
Core container
Data Access modules - JDBC/ORM
A Banking application business layer has been developed using Spring Core and AOP modules, data access layer using Spring Data Access/Integration module. The development team wants to implement the presentation tier of the application using simple Model-View-Controller architecture.
webmvc
web
Spring IoC
IOC
Inversion of Control(IoC) helps in creating a more loosely coupled application. IoC represents the inversion of the responsibility of application object's creation, initialization and destruction from the application to the third party such as framework. Now the third party takes care of application object management and dependencies there by 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). Introduction to Spring Inversion of Control(IoC)
Spring container managed application objects are called beans in Spring.
We need not create objects in depenedency 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.
Benefits of Dependency Injection(DI):
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.
SPRING IOC
The core container module of Spring framework provide 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.
Application logic is provided through POJO classes.
Configuration metadata consists of bean definitions that the container must manage.
IoC container produces objects required by the application using POJO classes and configuration metadata. IoC container is of two types – BeanFactory and ApplicationContext.
Spring provides two types of containers
BeanFactory:
It is the basic Spring container with features to instantiate, configure and manage the beans.
org.springframework.beans.factory.BeanFactoryis the main interface representing a BeanFactory container.
ApplicationContext:
ApplicationContext is one more Spring container that is more commonly used in Spring applications.
org.springframework.context.ApplicationContext is the main Interface representing an ApplicationContext container.
It inherits the BeanFactory features and provides added features to support enterprise services such as internationalization, validation, etc.
ApplicationContext is the preferred container for Spring application development. Spring IoC - Containers
org.springframework.context.support.ClassPathXmlApplicationContext isone of the most commonly used implementation of ApplicationContext.
ApplicationContext container is instantiated by loading the configuration from the config.xml file available in CLASSPATH of the application.
Accessing the bean with id "reportService" from the container.
BeanFactory
ApplicationContext
Does not support annotation based Dependency Injection.
Support annotation based Dependency Injection.
Does not support enterprise services.
Support enterprise services such as validations, internationalization, etc.
By default it support Lazy Loading.
// Loading BeanFactory BeanFactory factory = new ClassPathXmlApplicationContext (“config.xml”);
// Instantiating bean during first access using getBean() ReportService reportService = factory.getBean(”reportService”);
By default it support Eager Loading.Beans are instantiated during load time.
// Loading ApplicationContext and instantiating bean ApplicationContext context = new ClassPathXmlApplicationContext(“config.xml”);
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
Spring IoC – XML based Configuration Metadata
In XML configuration, the configuration metadata is provided as a simple XML file describing bean definitions that the Spring container has to manage. Basic XML based configuration structure is as follows:
Bean is the root element & also includes namespace declarations
Bean definition
id attribute represents a unique bean identifier
class attribute represents a fully qualified class name
Demo : Spring IoC
Highlights:
To understand how to define a bean in the configuration file
Learn how to access bean and instantiate Spring container in an application
Demosteps:
Objective
To understand how to instantiate ApplicationContext, define a bean in the configuration file and also learn how to access the bean in Spring application.
Required Files
ReportService.java
config.xml
Client.java
Required Jars
spring-core-5.0.5.RELEASE.jar
spring-beans-5.0.5.RELEASE.jar
spring-context-5.0.5.RELEASE.jar
spring-expression-5.0.5.RELEASE.jar
spring-jcl-5.0.5.RELEASE.jar
Demo Steps
Step 1: Create a project as follows
File -> New -> Other -> Java Project -> Provide name of the project(demo1-spring-ioc) and click Finish
Step 2: Create a package "com.infosys.service" as below
Right click on src folder -> New -> Package -> Provide package name(com.infosys.service) and click Finish
Step 3: Create a class "ReportService.java" as below
Right click on com.infosys.service package -> New -> Class -> Provide class name (ReportService.java) and click Finish.Write below code.
package com.infosys.service;
publicclassReportService{
publicvoid display(){
System.out.println("Hi, Welcome to Report Generation application");
}
}
Step 4: Create a configuration file "config.xml" as below with required bean definitions
Right click on src folder New -> Other -> XML -> XML file -> click on Next -> Provide xml file name(config.xml) and click Finish. Write below code in "config.xml" file
com.infosys.service.ReportService --> Fully qualified class name
Best Practices
It is a recommended good practice to have bean id same as class name lowering first letter.
From Spring 4.x onwards, it is NOT recommended to specify the version details explicitly for the referenced xsd's in the declaration section. Spring takes care of version details from the application classpath.
Spring configuration xml file name is user defined and hence you can give any meaningful name of your choice.
Step 5: Follow the below step to add required jars to the classpath
Right click on project -> Properties -> Java Build Path -> Choose "Libraries" option -> Click on "Add External JARs" -> Browse and add required jars and click OK
Step 6: Create a package "com.infosys.client" and then create a class "Client.java" in this package and below code.
*
* The Class Client.
*/
publicclassClient{
publicstaticvoid main(String[] args){
//ApplicationContext container is instantiated by loading the configuration from config.xml available in application classpath
// Invoking display method of ReportService to display greeting on console
reportService.display();
}
}
Step 7: Follow the below step to run the application
Right click on Client file(which has main method)-> Run As -> Java Application
Output
You can observe below response on the console.
Note:
Since we are not explicitly closing the context in the client code, there will be a warning for resource leakage, you can use one more interface from Spring "AbstractApplicationContext" as shown below which has a method to close the context explicitly.
Consider the previous demo to display the welcome message using Spring.
In the client code Client.java
Replace bean access line "ReportService reportService = (ReportService ) context.getBean("reportService");" with this"ReportService reportService = context.getBean(ReportService.class);"
Run the application and observe the response
--@ work same as normal
Now, in the configuration file config.xml
Define one more bean of ReportService class with id reportService2
Run the application and observe the response
--@Exception in thread "main" org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type 'com.infosys.service.ReportService' available: expected single matching bean but found 2: reportService,reportService2
In the client code
Now use this line for accessing bean "ReportService reportService = context.getBean("reportService2", ReportService.class);"
Run the application and observe the response.
--@code will work as normal
There are different ways to access bean in Spring
1. Traditional way of accessing bean based on bean id with explicit type cast
This is same as the below Java code wherein an instance is created and initialized with default values using default constructor.
ReportService reportService =newReportService();
How do we initialize bean with some specific values in Spring?
This can be achieved through Dependency Injection in Spring.
Inversion of Control pattern is achieved through Dependency Injection (DI) in Spring. In Dependency Injection, 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:This is achieved when the container invokes parameterized constructor to initialize the properties of a class
Types:
Primitive values
by name = constructor-argname="totalRecords"value="500"/,
type = constructor-argvalue="200.00"type="double"/,
index= constructor-argvalue="500"index="1"/
Non Primitiveconstructor-argname="master"ref="pdfReportGenerator"/
Setter Injection:This is achieved when the container invokes setter methods of a class to initialize the properties after invoking a default construct
Constructor Injection - Primitive values
Let us consider the ReportService class of Report Generation application to understand constructor injection.
ReportService class has a recordsPerPage property, let us now modify this class to initialize recordsPerPage property during bean instantiation using constructor injection approach.
package com.infosys.service;
publicclassReportService{
privateint recordsPerPage;
publicReportService(int recordsPerPage){
this.recordsPerPage = recordsPerPage;
}
--------------------
}
How do we define bean in the configuration to initialize values?
Here first value "100" is passed to recordsPerPage and second value "500" to totalRecords of the parameterized constructor. By default, values are supplied based on the sequence in which the constructor-arg's are defined in a bean definition.
By default, constructor-arg value is of type String specified within double quotes(" "). In case of different constructor argument type, Spring takes care of converting assigned String value to appropriate constructor arguments type if it is Java compatible conversion otherwise throws an exception. Quiz:
How does Spring resolve ambiguities if any in terms of passing values to parameterized constructor?
FromSpring 3.0onwards, constructor parametername can be used for providing value as shown below. Here the values are passed to appropriate constructor arguments based on argument name instead of in the order of sequence mentioned in the bean definition.
Now, Spring passes values to constructor arguments based on matching type of argument instead of default sequence. Hence value "200.00" is assigned to 2nd argument of constructor and value "50" to the first argument considering the type of values.
The main method for the application includes the following instructions:
ApplicationContext ac=new ClassPathXmlApplicationContext("config.xml");
MobileService m = (MobileService)ac.getBean("mobileService");
What will happen when we execute the above main method?
The default constructor of the MobileService class will be called to create instance and initialize with the default values as mobileNumber with 0 and model with null.
Throws an exception as no values are passed to the parameterized constructor using constructor-arg tag in the bean definition
Throws an exception : no matching constructor found
Q3 of 5
Consider MobileService classwith two properties mobileNumber and model as shown below.
package com.infosys;
public class MobileService{
private long mobileNumber;
private String model;
//parameterized constructor
public MobileService(long mobileNumber, String model){
this.mobileNumber = mobileNumber;
this.model = model;
}
}
Observe in the above code, ReportGenerator property of ReportSevice class has not been initialized with any value in the code. This is because in Spring dependency is going to be taken care in the configuration.
How do we inject object dependencies through configuration using constructor injection?
We can inject dependent object using constructor-arg tag with "ref" attribute. Following configuration is required for Spring to inject dependency of ReportGenerator through parameterized constructor.
For object dependency, constructor-arg tag has to be used to inject the dependency by referring to the required bean present in the container using ref attribute. Here, pdfReportGenerator bean has been injected to reportService bean using ref attribute of constructor-arg tag in reportService bean definition.
Demo
Highlights:
Objective :To understand the constructor based dependency injection in Spring
Required Jars: Same as Demo1
Demosteps:
ReportGenerator.java --> Interface
package com.infosys.demo;
publicinterfaceReportGenerator{
publicString generateReport(int recordsPerPage);
}
HTMLReportGenerator.java --> Implementation of ReportGenerator interface
InfyGo company provides different travel services to its customers. There are many employees working in the company to provide these services to the customers. InfyGo requires a simple application to manage its employee details and also the loan details which the company offers to its employees based on their role.
Following are the required functionalities:
Add new Employee details
Get Employee details
Check Loan Eligibility based on the following criteria
"Manager" and "GM" roles are not eligible for applying for a loan
If an employee already has taken a loan and it is still not closed also not eligible for the loan
Application Architecture
Class Description
Employee.java
publicclassEmployee{
privateint empId;
privateString firstName;
privateString lastName;
privateString role;
privateString department;
privateAddress address;
}
Address.java
publicclassAddress{
privateString city;
privateString state;
privateint pincode;
}
Loan.java
publicclassLoan{
privateint loanId;
privateint empId;
privatedouble amount;
privatedouble emi;
privateint noOfInsatllment;
privatedouble balance;
/** The status. It can be either "open" or "closed" state */
privateString status;
}
The complete code of this requirement is already implemented using Java. You can refer to demo2-employee-java-application from the downloaded demos.
Now, as part of this exercise convert the above given Java application to Spring application by introducing the following Spring core concepts.
Define required bean definitions by initializing needed dependency using constructor injection in the Spring configuration
Client code has to access the EmployeeService bean to get the services
Summary:
In this exercise,
You have learned how to implement construct injection to initialize the dependencies
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?
Bean definition with property tag is used for setter injection.
Primitive setter injection Consider the below example to understand setter injection for primitive types.
Following ReportService class has a recordsPerPage property, let us see how to initialize this property during bean instantiation using setter injection approach.
package com.infosys.demo;
publicclassReportService{
privateint recordsPerPage;
publicint getRecordsPerPage(){
return recordsPerPage;
}
publicvoid setRecordsPerPage(int recordsPerPage){
this.recordsPerPage = recordsPerPage;
}
--------------------------
}
How do we define bean in the configuration to initialize values?
As shown above,the property tag has to be used along with attribute name specifying the respective property name of the class to initialize the value.
What is mandatory to implement setter injection?
Default constructor and setter methods of respective dependent properties are required in the ReportService class. For setter injection, Spring internally uses the default constructor to create a bean and then invokes setter method of the respective property based on name attribute in order to initialize the values.
property tag in the bean definition
Non Primitive injection How do we inject object dependencies using setter injection?
We can inject dependent object using property tag with "ref" attribute as shown in the below example.
Consider the ReportService class of Report generation application.
package com.infosys.demo;
publicclassReportService{
privateReportGenerator master;
publicvoid setMaster(ReportGenerator master){
this.master = master;
}
publicReportGenerator getMaster(){
return master;
}
-----------------------------------
}
Following configuration is required for Spring to inject dependency of ReportService through setter injection.
Let us assume HTMLReportGenerator and PDFReportGenerator classes are present.
For object dependency, property tag has to be used along with the name attribute to inject the dependency by referring to the required bean present in the container using ref attribute.
Here, Spring creates ReportService bean with required dependency by invoking default constructor and then setMaster() method of ReportService class to initialize the dependent bean. Demo
Highlights:
Objective:To understand the setter based dependency injection in Spring
Required Jars: Same as Demo1
Demosteps:
ReportGenerator.java --> Interface
package com.infosys.demo;
publicinterfaceReportGenerator{
publicString generateReport(int recordsPerPage);
}
HTMLReportGenerator.java --> Implementation of ReportGenerator interface
bean id = "reportService" class = "com.infosys.demo.ReportService"
property name = "reports"
list
ref bean = "PDFReportGenerator /
ref bean = "HTMLReportGenerator /
/list
/property
/bean
Observation:
The dependency of ReportService class on ReportGenerator type of object has been resolved using the new operator in the ReportService class
As discussed earlier, the use of new operator makes application tightly coupled and hence any changes to the dependencies require appropriate code change and becomes tedious as the application grows.
Now, let us re-look at the same application implemented using Spring. You can refer to the demo implemented as part of the constructor/setter injection.
Observation:
The dependency of ReportService class on ReportGenerator type of object has been moved to Spring configuration
Now, the Spring container is responsible for instantiating and injecting required dependencies based on bean definitions provided through configuration. Hence the application is relieved from looking for dependent objects and also it is very easy to change the dependencies based on the need without doing much changes to the code.
Dependency Injection helped in creating a more loosely coupled application.
Quiz:
Q1 of 4
Consider the MobileService class given below:
package com.infosys;
public class MobileService{
private long mobileNumber;
private String model;
public void setMobileNumber(long mobileNumber){
this.mobileNumber = mobileNumber;
}
public void setModel(String model){
this.model = model;
}
}
A Spring configuration file(config.xml) defines a bean of Mobile class as shown below:
b)Assume BookRepository is present in com.infosys.repository package
*bean id="bookService" class = "com.infosys.service.BookService"*
*property name="bookRepositories"*
*list*
*bean id ="bookRepository1" class = "com.infosys.repository.BookRepository/*
*bean id ="bookRepository2" class = "com.infosys.repository.BookRepository/*
*/list*
*/property*
*/bean
c) Spring provides support for all the collection types such as List, Set, Map
d) Spring does not support collection in the bean definition
Exercise : Setter Injection
ProblemStatement 1:
Consider the Constructor InjectionExercise solution implemented for Employee scenario.
Now, as part of this exercise
Use setter injection for initializing the required bean dependencies in the Spring configuration
Summary: In this exercise,
You have learned how to implement setter injection to initialize the dependencies
ProblemStatement 2 :
Consider the previous exercise solution implemented for Employee application.
As part of this exercise, update Spring configuration for the following
Use setter injection for initializing loanService bean dependency
Use constructor injection for initializing employeeService bean dependencies
Summary: In this exercise,
You have learn how to implement both construct injection and setter injection to initialize the dependencies
Exercise : Constructor And Setter Injection
ProblemStatement:
Consider the previous exercise solution implemented for Employee application.
As part of this exercise, update Spring configuration for the following
Use setter injection for initializing loanService bean dependency
Use constructor injection for initializing employeeService bean dependencies
Summary: In this exercise,
You have learned how to implement both construct injection and setter injection to initialize the dependencies
Comparison Constructor Injection and Setter Injection
Constructor Injection
Setter Injection
Dependency Injection is through parameterized constructor
Dependency Injection is through setter methods after invoking the default constructor
Need parameterized constructor in the POJO class
Need default constructor and setter methods in the POJO class
tag is used in configuration file
tag is used in configuration file
tag "ref" attribute is used to provide dependency for Object type
tag "ref" attribute is used to provide dependency for Object type
Preferred for
mandatory dependencies
Immutable dependencies
concise(pass several parameters once)
optional / changeable dependencies
circular dependencies
Analyze : Dependency Injection
ProblemStatement:
Consider the below given GreetingService class which is having dependency on GreetingUtilbean.
This bean instantiation uses constructor injection for bean dependencies and hence internally appropriate parameterized constructor of GreetingService class has been invoked.
Below is the equivalent Java code of above-given bean definition.
Bean instantiation uses default constructor followed by setter method of specified property for injecting dependency. Hence default constructor and then appropriate setter method of GreetingService class has been invoked automatically.
Below is the equivalent Java code of above given bean definition.
It is not required to specify all the properties values while defining bean in the configuration. For non-primitive properties we can use the Autowiring feature.
If Autowiring is enabled, Spring container automatically initializes the dependencies of that bean.
There is no need to provide explicit property or constructor-arg with ref tags in the bean definition for object dependencies.
Autowiring cannot be used to inject primitive and string values.
Spring automatically inject the bean dependency. The autowiring has four modes.
no (no autowiring)
byName
byType
constructor
In XML configuration, autowire mode is specified in the bean definition using the autowire attribute.
Autowiring Modes
Mode
Description
byName
Bean dependency is autowired based on the property name
If the matching bean does not exist in the container then bean will remain unwired
It internally uses setter injection
byType
Autowiring the bean dependency based on the property type
Properties for which there is no matching bean will remain unwired.
Spring throws an exception if there is more than one bean of the same type exists in the container
It internally uses setter injection
constructor
It is the same as autowiring byType but through constructor arguments.
Spring autowire the dependency based on constructor argument type through constructor injection.
Spring throws an exception if there is more than one bean of same type exists in the container
no
Default mode which means no autowiring
Autowiring using byName mode
Autowired using "byName" mode in Spring.
In byName mode, Spring looks for a bean in the container with id same as property name to autowire the dependency.
In the below given code, ReportService class is dependent on ReportGenerator bean.
package com.infosys.demo;
publicclassReportService{
privateReportGeneratormaster;
privateint recordsPerPage;
---------------------------
}
For autowiring byName, following details are required in the configuration.
Define bean ofReportGenerator with id same as property name (Here it is "master" in the above class)
Mention an attribute autowire value "byName" in the reportServicebean definition as shown below.
In byName mode, it is mandated to have bean id same as the property name and also the respective setter methods as Spring inject the bean dependency internally using setter injection. above eg has propertyname(class) and bean id (xml) as master
Highlights:
Objective:To apply Autowiring value "byName" in XML configuration
Required Jars: Same as Demo1
Demosteps:
ReportGenerator.java --> Interface
package com.infosys.demo;
publicinterfaceReportGenerator{
publicString generateReport(int recordsPerPage);
}
HTMLReportGenerator.java --> Implementation of ReportGenerator interface
The main method for the application is defined as follows:
ApplicationContext ac= new ClassPathXmlApplicationContext(“config.xml");
PersonService p1= (PersonService) ac.getBean("personService");
System.out.println("I have : "+p1.getMob().getMobileName());
Ans : throws null pointer exception
Explanation :
Yes, you are right!
Autowiring using 'byName' injects dependencies based on the name of the property. As there is, no bean registered to Spring container with the name as 'mob'. The mob property of PersonService class remains unwired.
The mobile name is not displayed as an exception is thrown.
Autowiring using byType mode
Let us understand how the bean dependencies are autowired using "byType" mode in Spring.
In byType mode, Spring looks for the bean in the container based on type of bean to autowire the dependency.
In the below given code, ReportService class is dependent on ReportGenerator bean.
package com.infosys.demo;
publicclassReportService{
privateReportGenerator master;
privateint recordsPerPage;
------------------------------
}
In order to use autowiring byType, we need to provide following details in the configuration.
Define bean of ReportGenerator with any bean id
Mention an attribute autowire value "byType" in the reportService bean definition as shown below.
In the below given code, ReportService class is dependent on ReportGenerator bean.
In byType mode, there is no mandate to have bean id same as property name as the dependency now is autowired based on type of property instead of the name. byType also requires the respective setter methods in the class as Spring inject the bean dependency internally using setter injection.
In the previously discussed autowire byName demo, modify autowire attribute value to "byType" in the reportService bean definition and execute the demo.
Quiz
Consider the following classes defined in a Spring Application:
package com.infosys.service;
public class MobileService {
private String mobileName;
public MobileService() { }
//getter and setter methods
}
package com.infosys.service;
public class PersonService {
private MobileService mob;
//getter and setter methods
}
The Spring configuration file includes the following declarations:
The main method for the application is defined as follows:
ApplicationContext ac= new ClassPathXmlApplicationContext(“config.xml");
PersonService p1= (PersonService) ac.getBean("personService");
System.out.println("I have : "+p1.getMob().getMobileName());
Runtime Exception
Explanation :
In the byType mode, dependency will be autowired based on the type of property. As there is more than one bean is available in the matching type it leads to an UnsatisfiedDependancyException
The mobile name is not displayed as an Exception is thrown.
ProblemStatement:
Consider the previous demo implemented for byType autowiring.
Modify the ReportGenerator reference name from "master" to "reportGenerator" in ReportService class.
Execute and analyze the response.
2. Now, define two beans of ReportGenerator class in the configuration.
Execute and analyze the response.
Summary:
In this exercise,
You have learned that bean id can be different from property name for wiring dependency using byType
There has to be single bean of the required type in the container for byType autowiring
constructor mode
how the bean dependencies are autowired using "constructor" mode in Spring.
In this mode, Spring does autowiring of beans internally byType similar to that of byType mode however here the dependency is injected using constructor injection instead of setter injection. Hence it is required to have parameterized constructor in the respective class.
In the below-given code, ReportService class is dependent on ReportGenerator bean.
In constructor mode of autowiring, again there is no mandate to have bean id same as property name as the dependency now is autowired based on type of property instead of the name. However it is mandatory to have parametarized constructor in the ReportService class because the dependency is now injected through the constructor.
Demo : Autowiring by constructor mode
Highlights:
Objective: To learn how to apply Autowiring by constructor mode.
Required Jars: Same as Demo1
Demosteps:
ReportGenerator.java --> Interface
package com.infosys.demo;
publicinterfaceReportGenerator{
publicString generateReport(int recordsPerPage);
}
HTMLReportGenerator.java --> Implementation of ReportGenerator interface
The main method for the application is defined as follows:
ApplicationContext ac= new ClassPathXmlApplicationContext(“config.xml");
PersonService p1= (PersonService) ac.getBean("personService");
System.out.println("I have : "+p1.getMob().getMobileName());
What is the output of the above code execution?
Person: Parameterized Constructor I have : Nokia
Explanation :
Accessing the mobileName property using PersonService instance is possible. It will return the mobileName value.As the autowiring is done by constructor, the default constructor is not called. The value of mobileName attribute is set to Nokia, and not null
no mode
Another mode of autowiring is "no", which means no autowiring. Dependency is explicitly wired using property name="propertyName" ref="beanId" in setter injection or constructor-arg ref="beanId" in constructor injection configuration in the configuration.
In the below-given code, ReportService class is dependent on ReportGenerator bean.
package com.infosys.demo;
publicclassReportService{
privateReportGenerator master;
privateint recordsPerPage;
------------------------------------
}
Following is the required configuration, wherein reportService bean dependent beans are explicitly autowired.
In the previous demo, modify the autowire attribute value to "no" in the Spring configuration reportService bean definition, inject the required dependency explicitly and observe the result.
Quiz
Consider the following classes defined in a Spring Application:
package com.infosys.service;
public class MobileService {
long mobileNumber;
String model;
public MobileService(long mobileNumber, String model) {
this.mobileNumber = mobileNumber;
this.model = model;
}
public MobileService() {
}
//getter and setter methods
}
package com.infosys.service;
public class PersonService {
private Mobileservice mobile;
//getter and setter methods
}
The Spring configuration file includes the following declarations:
The main method for the application is defined as follows:
ApplicationContext ac= new ClassPathXmlApplicationContext(“config.xml");
PersonService p1= (PersonService) context.getBean("personService");
System.out.println(p1.getMobile().getModel());
ANs : Throws Exception
Explanation :
Since autowire is set to no mode, the spring container will not initialize the dependencies of that bean automatically, the dependencies should be explicitly wired.
The mobile name will not be displayed as an Exception is thrown.
Autowiring Mode
Description
byName
Autowiring based on bean name through setter injection
byType
Autowiring based on bean type through setter injection
constructor
Autowiring based on the bean type through parameterized constructor
no
No Autowiring, required dependency has to be injected explicitly using property or constructor-arg ref attribute in bean definition
Bean Scope
The lifetime of a bean depends on its scope. Bean's scope can be defined while declaring it in the configuration metadata file.
A bean can be in singleton or prototype scope.
A bean with "singleton" scope is initialized during the container starts up and the same bean instance is provided for every bean request from the application.
However in case of "prototype" scope, a new bean instance is created for every bean request from the application.
Bean Scope - singleton
There will be a single instance of "singleton" scope bean in the container and the same bean is given for very request from the application.
In XML configuration, bean scope is specified using the "scope" attribute as shown in the below example.
Here, reportService bean is defined as singleton scope.
In the above example, both reportService and htmlReportGenerator (since attribute scope does not exist in the bean definition, by default it is a singleton) beans are in singleton scope.
Let us access reportService bean in the client class more than once and compare their hashCode to see whether we are getting the same bean or different bean.
System.out.println("hash code of srv1:"+ srv1.hashCode());
System.out.println("hash code of srv2:"+srv2.hashCode());
if(srv1==srv2){
System.out.println("Same instance");
}
else
System.out.println("Different instance");
}
}
Execution of the above client code gives below result.
hash code of srv1:1690287238
hash code of srv2:1690287238
Same instance
In the above output response, you can see that hashCode of srv1 and srv2 are same indicating they both are referring to same bean instance in the container.
For "prototype" bean, there will be a new bean created for every request from the application.
In the below given example, reportService bean is defined with prototype scope. There will be a new reportService bean created for every bean request from the application.
A service class called MobileService is defined with two member variables mobileNo and model in the package com.infosys.service. A default constructor and getter and setter methods are also defined in this class. A Spring configuration file includes the following bean definitions:
Ans : false
Explanation :
Yes, you are right!!
Since the scope of the bean is prototype a new object is created for every request, so both “mobile1” and “mobile2” objects are different.
No Exception is thrown as a given bean can be accessed any number of times.