Spring Core Module
Spring Core Module
By –
Dilip Singh
dilipsingh1306@gmail.com
dilipsingh1306
Shortly, it is a set of keywords and rules of their usage that allows a programmer to tell a
computer what to do. From a technical point of view, there are many ways to classify
languages - compiled and interpreted, functional and object-oriented, low-level and high-
level, etc..
➢ The server part. This is where all the "heavy" calculations take place, background API
interactions, Database write/read operations, etc.
Languages Used : Java, .net, python etc..
➢ The client part. For example, the interface of your website, mobile applications, desktop
apps, etc.
Languages Used : HTML, Java Script, Angular, React etc.
Obviously, there can be much more than two languages in the project, especially considering
such things as SQL used for database operations.
What is a Framework?
When choosing a technology stack for our project, we will surely come across such as
framework. A framework is a set of ready-made elements, rules, and components that
simplify the process and increase the development speed. Below are some popular
frameworks as an example:
➢ It will save time. Using premade components will allow you to avoid reinventing the logics
again and writing from scratch those parts of the application which already exist in the
framework itself.
➢ It will save you from making mistakes. Good frameworks are usually well written. Not
always perfect, but on average much better than the code your team will deliver from
scratch, especially when you're on a short timeline and tight budget.
➢ Opens up access to the infrastructure. There are many existing extensions for popular
frameworks, as well as convenient performance testing tools, CI/CD, ready-to-use
boilerplates for creating various types of applications.
Conclusion:
The framework provides a comprehensive programming and configuration model for modern
Java-based enterprise applications, with support for features such as dependency injection,
aspect-oriented programming, data access, and transaction management. Spring handles the
infrastructure so you can focus on your application. A key element of Spring is infrastructural
support at the application level: Spring focuses on the "plumbing" of enterprise applications
so that teams can focus on application-level business logic, without unnecessary ties to
specific deployment environments.
One of the key features of the Spring Framework is its ability to promote loose coupling
between components, making it easier to develop modular, maintainable, and scalable
applications. The framework also provides a wide range of extensions and modules that can
be used to integrate with other technologies and frameworks, such as Hibernate, Struts, and
JPA.
Overall, the Spring Framework is widely regarded as a powerful and flexible framework for
building enterprise-level applications in Java.
Overall, Spring Framework has become one of the most popular Java frameworks due to its
ease of use, modularity, and extensive features. It is widely used in enterprise applications,
web applications, and other types of Java-based projects.
Spring continues to innovate and to evolve. Beyond the Spring Framework, there are other
projects, such as Spring Boot, Spring Security, Spring Data, Spring Cloud, Spring Batch, among
others.
The Spring Framework includes several modules that provide a range of services:
• Spring Core Container: this is the base module of Spring and provides spring containers
(BeanFactory and ApplicationContext).
• Aspect-oriented programming: enables implementing cross-cutting concerns.
• Data access: working with relational database management systems on the Java platform
using Java Database Connectivity (JDBC) and object-relational mapping tools and
with NoSQL databases
• Authentication and authorization: configurable security processes that support a range
of standards, protocols, tools and practices via the Spring Security sub-project.
• Model–View–Controller: an HTTP- and servlet-based framework providing hooks for web
applications and RESTful (representational state transfer) Web services.
• Testing: support classes for writing unit tests and integration tests
1. Lightweight: Spring is a lightweight framework, which means it does not require a heavy
runtime environment to run. This makes it faster and more efficient than other
frameworks.
2. Inversion of Control (IOC): The Spring Framework uses IOC to manage dependencies
between different components in an application. This makes it easier to manage and
maintain complex applications.
3. Dependency Injection (DI): The Spring Framework also supports DI, which allows you to
inject dependencies into your code at runtime. This makes it easier to write testable and
modular code.
4. Modular: Spring is a modular framework, which means you can use only the components
that you need. This makes it easier to develop and maintain applications.
5. Loose Coupling: The Spring applications are loosely coupled because of dependency
injection.
6. Integration: The Spring Framework provides seamless integration with other frameworks
and technologies such as Hibernate, Struts, and JPA.
7. Aspect-Oriented Programming (AOP): The Spring Framework supports AOP, which allows
you to separate cross-cutting concerns from your business logic. This makes it easier to
develop and maintain complex applications.
8. Security: The Spring Framework provides robust security features such as authentication,
authorization, and secure communication.
9. Transaction Management: The Spring Framework provides robust transaction
management capabilities, which make it easier to manage transactions across different
components in an application.
10. Community Support: The Spring Framework has a large and active community, which
provides support and contributes to its development. This makes it easier to find help and
resources when you need them.
Overall, the Spring Framework provides a number of advantages that make it a popular choice
among developers. Its lightweight, modular, and flexible nature, along with its robust features
for managing dependencies, transactions, security, and integration, make it a powerful tool
for developing enterprise-level Java applications.
➢ Works on POJOs (Plain Old Java Object) which makes your application lightweight.
➢ Provides predefined templates for JDBC, Hibernate, JPA etc., thus reducing your effort
of writing too much code.
➢ Because of dependency injection feature, your code becomes loosely coupled.
➢ Using Spring Framework, the development of Java Enterprise
Edition (JEE) applications became faster.
➢ It also provides strong abstraction to Java Enterprise Edition (JEE) specifications.
➢ It provides declarative support for transactions, validation, caching and formatting.
The below table represents the differences between Java and Spring:
Java Spring
Java is one of the prominent programming Spring is a Java-based open-source
languages in the market. application framework.
Spring Framework comes with various
Java provides a full-highlighted Enterprise
modules like Spring MVC, Spring Boot, Spring
Application Framework stack called Java EE
Security which provides various ready to use
for web application development
features for web application development.
Java EE is built upon a 3-D Architectural Spring is based on a layered architecture that
Framework which are Logical Tiers, Client consists of various modules that are built on
Tiers and Presentation Tiers. top of its core container.
Since its origin till date, Spring has spread its popularity across various domains.
1. Spring Core: This module is the core of the Spring Framework. It provides an
implementation for features like IoC (Inversion of Control) and Dependency Injection with
a singleton design pattern.
2. Spring Bean: This module provides an implementation for the factory design pattern
through BeanFactory.
3. Spring Context: This module is built on the solid base provided by the Core and the Beans
modules and is a medium to access any object defined and configured.
Spring Bean:
Beans are java objects that are configured at run-time by Spring IoC Container. In
Spring, the objects of your application and that are managed by the Spring IoC container are
called beans. A bean is an object that is instantiated, assembled, and managed by a Spring IoC
container. Otherwise, a bean is simply one of many objects in your application. Beans, and
the dependencies among them, are reflected in the configuration metadata used by Spring
container.
When we hear the term dependency, what comes on to our mind? Obviously, something
relying on something else for support right? Well, that’s the same, in the case of programming
also.
Dependency Injection in Spring can be done through constructors, setters or fields. Here's
how we would create an object dependency in traditional programming:
Employee.java
public class Employee {
private String ename;
private Address addr;
public Employee() {
this.addr = new Address();
}
// setter & getter methods
}
Address.java
By using DI, we can rewrite the example without specifying the implementation of
the Address that we want:
Inversion of Control:
The IoC container is responsible to instantiate, configure and assemble the objects. The IoC
container gets information’s from the XML file or Using annotations and works accordingly.
If I have to explain you in simpler terms, then consider an example, wherein you have the
ability to cook. According to the IoC principle, you can invert the control, so instead of you
cooking food, you can just directly order from outside, wherein you receive food at your
doorstep. Thus the process of food delivered to you at your doorstep is called the Inversion
of Control.
You do not have to cook yourself, instead, you can order the food and let a delivery executive,
deliver the food for you. In this way, you do not have to take care of the additional
responsibilities and just focus on the main work.
Spring – BeanFactory:
This is the simplest container providing the basic support for DI and defined by the
org.springframework.beans.factory.BeanFactory interface. BeanFactory interface is the
simplest container providing an advanced configuration mechanism to instantiate, configure
and manage the life cycle of beans. BeanFactory represents a basic IoC container which is a
parent interface of ApplicationContext. BeanFactory uses Beans and their dependencies
metadata i.e. what we configured in XML file to create and configure them at run-time.
BeanFactory loads the bean definitions and dependency amongst the beans based on a
configuration file(XML) or the beans can be directly returned when required using Java
Configuration.
Spring ApplicationContext:
The following diagram shows a high-level view of how Spring Container works. Your
application bean classes are combined with configuration metadata so that, after the
ApplicationContext is created and initialized, you have a fully configured and executable
system or application.
Configuration Metadata:
As diagram shows, the Spring IoC container consumes a form of configuration
metadata. This configuration metadata represents how you, as an application developer, tell
the Spring container to instantiate, configure, and assemble the objects in your application.
Configuration metadata is traditionally supplied in a simple and intuitive XML format, which
is what most of this chapter uses to convey key concepts and features of the Spring IoC
container. These days, many developers choose Java-based configuration for their Spring
applications.
Instantiating a Container:
The location path or paths supplied to an ApplicationContext constructor are resource
Strings that let the container load configuration metadata from a variety of external
resources, such as the local file system, the Java CLASSPATH, and so on. The Spring provides
ApplicationContext interface: ClassPathXmlApplicationContext and FileSystemXmlApplicatio
nContext for standalone applications, and WebApplicationContext for web applications.
In order to assemble beans, the container uses configuration metadata, which can be in the
form of XML configuration or annotations. Here's one way to manually instantiate a
container:
BeanFactory ApplicationContext
It is a fundamental container that provides It is an advanced container that extends the
the basic functionality for managing beans. BeanFactory that provides all basic
functionality and adds some advanced
features.
It is suitable to build standalone It is suitable to build Web applications,
applications. integration with AOP modules, ORM and
distributed applications.
It supports only Singleton and Prototype It supports all types of bean scopes such as
bean scopes. Singleton, Prototype, Request, Session etc.
It does not support Annotation based It supports Annotation based configuration in
configuration. Bean Autowiring.
This interface does not provide messaging ApplicationContext interface extends
(i18n or internationalization) functionality. MessageSource interface, thus it provides
messaging (i18n or internationalization)
functionality.
BeanFactory will create a bean object when ApplicationContext loads all the beans and
the getBean() method is called thus making creates objects at the time of startup only
it Lazy initialization. thus making it Eager initialization.
NOTE: Usually, if we are working on Spring MVC application and our application is configured
to use Spring Framework, Spring IoC container gets initialized when the application started or
deployed and when a bean is requested, the dependencies are injected automatically.
However, for a standalone application, you need to initialize the container somewhere in the
application and then use it to get the spring beans.
In Maven Project, JAR files are always configured with pom.xml file i.e. we should not
download manually JAR files in any Project. In First Approach we are downloading JAR files
manually from Internet into our computer and then setting class Path to those jar file, this is
not recommended in Real time projects.
1. Open Eclipse
File -> new -> Project -> Java Project
Enter Project Name
Un-Select Create Module-Info
Click Finish.
I have uploaded copy of all Spring JAR files uploaded in Google Drive. You can download
from below link directly.
https://drive.google.com/file/d/1FnbtP3yqjTN5arlEGeoUHCrIJcdcBgM7/view?usp=dri
ve_link
Right Click on Project -> Build Path -> Configure Build Path -> Libraries -> ClassPath
With This Our Java Project is Supporting Spring Core Module Functionalities. We can
Continue with Spring Core Module Functionalities.
Now Open pox.xml file, add Spring Core JAR Dependencies to project and save it.
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>hello_spring</groupId>
<artifactId>hello_spring</artifactId>
<version>0.0.1-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>5.3.29</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.3.29</version>
</dependency>
</dependencies>
After adding Dependencies, Maven downloads all Spring Core Jar files with internal
dependencies of jars at the same time configures those as part of Project automatically. As
a Developer we no need to configure of jars in this approach. Now we can See Downloaded
JAR files under Maven Dependencies Section as shown in below.
With This Our Java Project is Supporting Spring Core Module Functionalities. We can
Continue with Spring Core Module Functionalities.
NOTE: Below Steps are now common across our Spring Core Project created by either
Manual Jar files or Maven Configuration.
package com.naresh.hello;
5. Now create a xml file with any name in side our project root folder:
Ex: beans.xml
6. Now Inside beans.xml, and paste below XML Shema content to configure all our bean
classes.
• Every class will be configured with <bean> tag, we can call it as Bean class.
• The id attribute is a string that identifies the individual bean name in Spring IOC Container
i.e. similar to Object Name or Reference.
• The class attribute is fully qualified class name our class i.e. class name with package
name.
8. Now create a main method class for testing.
Here we are getting the object of Student class from the Spring IOC container using
the getBean() method of BeanFactory. Let's see the code
package com.naresh.hello;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.support.FileSystemXmlApplicationContext;
FileSystemXmlApplicationContext("D:\\workspaces\\naresit\\hello_spring\\beans.xml");
➢ We can create multiple Bean Objects for same Bean class with multiple bean
configurations in xml file.
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
Bean Overview:
A Spring IoC container manages one or more beans. These beans are created with the
configuration metadata that you supply to the container (for example, in the form of XML
<bean/> definitions). Every bean has one or more identifiers. These identifiers must be unique
within the container that hosts the bean. A bean usually has only one identifier. However, if
it requires more than one, the extra ones can be considered aliases. In XML-based
configuration metadata, you use the id attribute, the name attribute, or both to specify bean
identifiers. The id attribute lets you specify exactly one id.
Instantiating Beans:
A bean definition is essentially a recipe for creating one or more objects. The container
looks at the recipe for a named bean when asked and uses the configuration metadata
encapsulated by that bean definition to create (or acquire) an actual object.
If you use XML-based configuration metadata, you specify the type (or class) of object that is
to be instantiated in the class attribute of the <bean/> element. This class attribute (which,
internally, is a Class property on a BeanDefinition instance) is usually mandatory.
1. Setter Injection
2. Constructor Injection
3. Filed Injection
There are many benefits to using dependency injection in Spring. Some of the benefits
include:
• Loose coupling: Dependency injection makes the classes in our application loosely
coupled. This means that the classes are not tightly coupled to the specific
implementations of their dependencies. This makes the classes more reusable and easier
to test.
• Increased testability: Dependency injection makes the classes in our application more
testable. This is because we can inject mock implementations of dependencies into the
classes during testing. This allows us to test the classes in isolation, without having to
worry about the dependencies.
• Increased flexibility: Dependency injection makes our applications more flexible. This is
because we can change the implementations of dependencies without having to change
the classes that depend on them. This makes it easier to change the underlying
technologies in our applications.
Dependency injection is a powerful design pattern that can be used to improve the design
and testability of our Spring applications. By using dependency injection, we can make our
applications more loosely coupled, increase their testability, and improve their flexibility.
Setter Injection:
Setter injection is another way to inject dependencies in Spring. In this approach, we specify
the dependencies in the class setter methods. The Spring container will then create an
instance of the class and then call the setter methods to inject the dependencies.
The <property> sub element of <bean> is used for setter injection. Here we are going to inject
1. Create a class.
package com.naresh.first.core;
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
From above configuration, <property> tag referring to setter injection i.e. injecting value to a
variable or property of Bean Student class.
3. Now get the bean object from Spring Container and print properties values.
package com.naresh.first.core;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.support.FileSystemXmlApplicationContext;
Output:
100
Dilip Singh
ABC College
This is Student class
76.0
2. Now from below line, we are getting bean object of Student class configured with bean id
: s1
package com.naresh.hello;
• For primitive and String data type properties of bean class, we can use both name and
value attributes.
• Now let’s test values injected or not from above bean configuration.
import org.springframework.context.ApplicationContext;
Output:
101
Dilip
2022
99.88
True
Now we are injecting/configuring Collection Data Types like List, Set and Map properties
into Spring Bean Object.
➢ For List data type property, Spring Provided <list> tag, sub tag of <property>.
<list>
<value> … </value>
<value>… </value>
<value> .. </value>
……………….
</list>
➢ For Set data type property, Spring Provided <list> tag, sub tag of <property>.
<set>
<value> … </value>
<value>… </value>
<value> .. </value>
……………….
</set>
➢ For Map data type property, Spring Provided <list> tag, sub tag of <property>.
<map>
<entry key="…" value="…" />
<entry key="…" value="…" />
package com.naresh.hello;
import java.util.List;
import java.util.Map;
import java.util.Set;
• Now let’s test values injected or not from above bean configuration.
package com.naresh.hello;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
Output:
101
Dilip
2022
99.88
true
[dilip@gmail.com, laxmi@gmail.com, dilip@gmail.com]
[8826111377, +1234567890]
{maths=88, science=66, english=44}
Now we are injecting/configuring other Bean Objects into another Spring Bean Object.
package com.naresh.training.spring.core;
public Address() {
System.out.println("Address instance/constructed ");
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public int getPincode() {
return pincode;
}
public void setPincode(int pincode) {
this.pincode = pincode;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
}
public Student() {
System.out.println("Student Constructor executed.");
}
public String getStudentName() {
return studentName;
}
public void setStudentName(String studentName) {
this.studentName = studentName;
}
public int getStudentId() {
return studentId;
}
public void setStudentId(int studentId) {
this.studentId = studentId;
}
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
}
➢ Now Configure Address and Student Bean classes. Here, Address Bean Object is
dependency of Student object i.e. Address should be referred inside Student. To achive
this collaboration, Spring provided ref element/attribute.
The ref element is the element inside a <property/> or <constructor-arg/> element. Here,
you set the value of the specified property of a bean to be a referenced to another bean (a
collaborator) managed by the container. Sometimes we can use ref attribute as part of
<property/> or <constructor-arg/>. We will provide bean Id for ref element which should be
injected into target Object. Please refer below, how to inject Bean Objects via ref element or
attribute.
<beans>
<bean id="universityAddress"
class="com.naresh.training.spring.core.Address">
<property name="city" value="Bangloore"></property>
<property name="country" value="India"></property>
<property name="pincode" value="400066"></property>
</bean>
<!-- Student Bean Objects -->
<bean id="student1" class="com.naresh.training.spring.core.Student">
<property name="studentName" value="Dilip Singh"></property>
<property name="studentId" value="100"></property>
<property name="address" ref="universityAddress"></property>
</bean>
<bean id="student2" class="com.naresh.training.spring.core.Student">
<property name="studentName" value="Naresh"></property>
<property name="studentId" value="101"></property>
<property name="address">
<ref bean="universityAddress"/>
</property>
</bean>
</beans>
➢ Now let’s test values and references injected or not from above bean configuration.
package com.naresh.training.spring.core;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.context.support.FileSystemXmlApplicationContext;
public class SpringSetterInjectionDemo {
Output:
Address instance/constructed
Student Contructor executed.
Student Contructor executed.
************ Student1 Data *********
100
Dilip Singh
Bangloore
India
400066
************ Student2 Data *********
101
Naresh
Bangloore
India
400066
From above output, same universityAddress bean Object is injected by Spring Container
internally inside both student1 and student2 Bean Objects.
Constructor Injection:
Example: Defining Bean Class With Primitive and String Data type.
package com.naresh.spring.di.ci;
• From the above Bean Configuration, Spring Container Internally passes values to
constructor of our class while creating Bean Object.
Testing:
package com.naresh.spring.di.ci;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
Output:
Finally, values are injected into properties of bean Object by executing constructor.
NOTE: When we are defining <constructor-arg> and values in Beans XML Configuration, we
should follow same order w.r.to Constructor Parameters.
Question: In any case, if we don't want to follow same order in beans configuration, do we
have any alternative solution?
Answer: Yes, Spring provided an attribute index as part of <constructor-arg> tag i.e. we
should provide index value for every property w.r.to Constructor Parameters Order. Here,
Index starts from 0 always.
Answer: Yes, We should configure every constructor parameter value inside bean
configuration in Spring i.e. From above example, Constructor Defined with 3 parameters in
Product class, so we should configure 3 values of <constructor-arg>.
If we are not configured same number of values respectively Spring will create an Exception
while creating Bean Object for that Bean Configuration.
• we can create many constructors in a Spring Bean class, and we should configure values
respectively for every bean Object with Constructor Injection.
Constructor Injection: Example with Collection Data Type and Another Object Reference.
package com.naresh.hello;
import java.util.Set;
}
public Address getCustomerAddress() {
return customerAddress;
}
public void setCustomerAddress(Address customerAddress) {
this.customerAddress = customerAddress;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getBalance() {
return balance;
}
public void setBalance(double balance) {
this.balance = balance;
}
public Set<String> getMobiles() {
return mobiles;
}
public void setMobiles(Set<String> mobiles) {
this.mobiles = mobiles;
}
}
package com.naresh.hello;
package com.naresh.hello;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
System.out.println(details.getName());
System.out.println(details.getBalance());
System.out.println(details.getMobiles());
System.out.println(details.getCustomerAddress().getFlatNo());
System.out.println(details.getCustomerAddress().getHouseName());
}
}
Output:
Dilip
500.0
[8826111377, +91-88888888, +232388888888]
333
Lotus Homes
Setter injection and constructor injection are two common approaches for
implementing dependency injection. Here are the key differences between them:
1. Dependency Resolution: In setter injection, dependencies are resolved and injected into
the target object using setter methods. In contrast, constructor injection resolves
dependencies by passing them as arguments to the constructor.
2. Timing of Injection: Setter injection can be performed after the object is created, allowing
for the possibility of injecting dependencies at a later stage. Constructor injection, on the
other hand, requires all dependencies to be provided at the time of object creation.
6. Testability: Constructor injection is generally favored for unit testing because it allows for
easy mocking or substitution of dependencies. By providing dependencies through the
constructor, testing frameworks can easily inject mocks or stubs when creating objects for
testing. Setter injection can also be used for testing, but it may require additional setup or
manipulation of the object's state.
The choice between setter injection and constructor injection depends on the specific
requirements and design considerations of your application. In general, constructor injection
is recommended when dependencies are mandatory and should be set once during object
creation, while setter injection provides more flexibility and optional dependencies can be set
or changed after object instantiation.
Bean wiring, also known as bean configuration or bean wiring configuration, is the process of
defining the relationships and dependencies between beans in a container or application
context. In bean wiring, you specify how beans are connected to each other, how
dependencies are injected, and how the container should create and manage the beans. This
wiring process is typically done through configuration files or annotations.
package com.naresh.hello;
package com.naresh.hello;
package com.naresh.hello;
public AccountDetails() {
}
public Address getCustomerAddress() {
return customerAddress;
}
public void setCustomerAddress(Address customerAddress) {
this.customerAddress = customerAddress;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public double getBalance() {
return balance;
}
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd">
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
AccountDetails details
= (AccountDetails) context.getBean(“accountDeatils”);
System.out.println(details.getName());
System.out.println(details.getBalance());
System.out.println(details.getMobiles());
//Get Address Instance
System.out.println(details.getCustomerAddress().getFlatNo());
//Get Area Instance
System.out.println(details.getCustomerAddress().getArea().getPincode());
}
}
Output:
Dilip
500.0
[8826111377, +91-88888888, +232388888888]
333
323232
AutoWiring in Spring:
Autowiring feature of spring framework enables you to inject the objects dependency
implicitly. It internally uses setter or constructor injection. In Spring framework, the
To use autowiring in an XML bean configuration file, you need to define the
“autowire” attribute for a bean definition. The “autowire” attribute accepts different values
to determine how autowiring should be performed. There are many autowiring modes.
1. no : This is the default value. It means no autowiring will be performed, and you need to
explicitly specify dependencies using the appropriate XML configuration using property of
constructor tags.
2. byName : The byName mode injects the object dependency according to name of the
bean i.e. Bena ID. In such case, property name of class and bean ID must be same. It
internally calls setter method. If a match is found, the dependency will be injected.
3. byType: The byType mode injects the object dependency according to type i.e. Data Type
of Property. So property/variable name and bean name can be different int this case. It
internally calls setter method. If a match is found, the dependency will be injected. If
multiple beans are found, an exception will be thrown.
4. constructor: The constructor mode injects the dependency by calling the constructor of
the class. It calls the constructor having large number of parameters.
Here’s an examples of using the “autowire” attribute in an XML bean configuration file.
autowire=no:
• Now Define Class Order which is having dependency of Product Object i.e. Product bean
object should be injected to Order.
Package com.flipkart.orders;
import com.flipkart.product.Product;
public Order() {
System.out.println(“Order Object Created by IOC”);
}
public Order(String orderId, double orderValue, Product product) {
super();
this.orderId = orderId;
this.orderValue = orderValue;
this.product = product;
}
public String getOrderId() {
return orderId;
}
public void setOrderId(String orderId) {
this.orderId = orderId;
}
public double getOrderValue() {
return orderValue;
}
public void setOrderValue(double orderValue) {
this.orderValue = orderValue;
}
public Product getProduct() {
return product;
}
public void setProduct(Product product) {
this.product = product;
}
• Now let’s configure both Product and Order in side beans xml file.
<beans>
<bean id=”product” class=”com.flipkart.product.Product”>
<property name=”productid” value=”101”></property>
<property name=”productName” value=”Lenevo Laptop”></property>
</bean>
<bean id=”order” class=”com.flipkart.orders.Order” autowire=”no”>
<property name=”orderId” value=”order1234”></property>
<property name=”orderValue” value=”33000.00”></property>
</bean>
</beans>
package com.flipkart.main;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.FileSystemXmlApplicationContext;
import com.flipkart.orders.Order;
import com.flipkart.orders.OrdersManagement;
import com.flipkart.product.Product;
// IOC Container
ApplicationContext context = new FileSystemXmlApplicationContext(
“D:\\workspaces\\naresit\\bean-wiring\\beans.xml”);
autowire=”byName”:
Now configure autowire=”byName” in side beans xml file for order Bean
configuration, because internally Product bean object should be injected to Order Bean
Object.In this autowire mode, We are expecting dependency injection of objects by Spring
instead of we are writing bean wiring with either using <property> and <constructor-arg> tags
by using ref attribute. Means, eliminating logic of reference configurations.
As per autowire=”byName”, Spring internally checks for a dependency bean objects which is
matched to property names of Object. As per our example, Product is dependency for Order
class.
Product class Bean ID = Property Name of Order class
• Internally Spring comparing as shown in above and injected product bean object to Order
object.
• Beans Configuration:
<beans>
<bean id="product" class="com.flipkart.product.Product">
<property name="productId" value="101"></property>
<property name="productName" value="Lenevo Laptop"></property>
</bean>
<bean id="order" class="com.flipkart.orders.Order" autowire="byName">
<property name="orderId" value="order1234"></property>
<property name="orderValue" value="33000.00"></property>
</bean>
</beans>
Test Our application and check Spring injected Product object or not inside Order.
autowire=”byType”:
Now configure autowire=”byType” in side beans xml file for Order Bean configuration,
because internally Product bean object should be injected to Order Bean Object. In this
Bean Data Type i.e. class Name = Data type of property of Order class
• Beans Configuration:
<beans>
<bean id="prod" class="com.flipkart.product.Product">
<property name="productId" value="101"></property>
<property name="productName" value="Lenevo Laptop"></property>
</bean>
<bean id="order" class="com.flipkart.orders.Order" autowire="byType">
<property name="orderId" value="order1234"></property>
<property name="orderValue" value="33000.00"></property>
</bean>
</beans>
• Test Our Application Now: Dependency Injected Successfully, because only One Product
Object available.
Test Our Application: We will get Exception while trying to inject Product Object because of
ambiguity between 2 Objects.
autowire=” constructor”:
Now configure autowire=”constructor” in side beans xml file for Order Bean
configuration, because internally Product bean object should be injected to Order Bean
Object. In this autowire mode, We are expecting dependency injected by Spring instead of we
are writing bean wiring with either using <property> or <constructor-arg> tags by using ref
attribute. Means, eliminating logic of reference configurations.
As per our example, Product is dependency for Order and Order class defined a constructor
with parameter contains Product type.
when autowire =constructor, spring internally checks out of multiple bean ids dependency
object which is matching with property name of Order class. If matching found then that
specific bean object will be injected. If not found then we will get ambiguity exception as
following.
As per our below configuration, both bean ids of Product are not matching with Order class
property name of Product type.
• Test Our Application: We will get Exception while trying to inject Product Object because
of ambiguity between 2 Objects.
Now if we configure one bean object of Product class with bean id which is matching with
property name of Order class. Then that Specific Object will be injected. From following
configuration Product object of bean id “product” will be injected.
Advantage of Autowiring:
• It requires less code because we don’t need to write the code to inject the dependency
explicitly.
Disadvantages of Autowiring:
• No control of the programmer.
The Latest Spring Framework supports 5 scopes, last four are available only if you use Web
aware of ApplicationContext i.e. inside Web applications.
1. singleton
2. prototype
3. request
4. session
5. application
6. websokcet
In XML configuration, we will use an attribute “scope”, inside <bean> tag as shown below.
singleton:
This is default scope of a bean configuration i.e. even if we are not provided scope
attribute as part of any bean configuration, then spring container internally consideres as
scope=”singleton”.
If Bean scope=singleton, then Spring Container creates only one object in side Spring
container overall application level and Spring Container returns same instance reference
always for every IOC container call i.e. getBean().
Product.java
public class Product {
private String productId;
private String productName;
public Product() {
System.out.println("Product Object Created by IOC");
}
• Now call Get Bean from IOC Container for Product Bean Object. In Below, we are calling
IOC container 3 times.
From above output, Spring Container created only one Object and same passed for every
new container call with getBean() by passing bean id. Means, Singleton Object created for
bean ID product in IOC container.
NOTE: If we created another bean id configuration for same class, then previous configuration
behaviour will not applicable to current configuration i.e. every individual bean configuration
or Bean Object having it’s own behaviour and functionality in Spring Framework.
Output:
For 2 Bean configurations of Product class, 2 individual Singleton Bean Objects created.
prototype:
If Bean scope defined as “prototype”, a new instance of the bean is created every time
it is requested from the container. It is not cached, so each request/call to IOC container for
the bean will return in a new instance.
Testing :
Now Spring Container created and returned every time new Bean Object for every
Container call getBean() for same bean ID.
request:
When we apply scope as request, then for every new HTTP request Spring will crates new
instance of configured bean. Only valid in the context of a web-aware Spring
ApplicationContext i.e. in web/MVC applications.
session:
application:
Once you have defined the application-scoped bean, Spring will create a single instance of the
bean per web application context. Any requests for this bean within the same web application
will receive the same instance.
It's important to note that the application scope is specific to web applications and relies on
the lifecycle of the web application context. Each web application running in a container will
have its own instance of the application-scoped bean.
You can use application-scoped beans to store and share application-wide state or resources
that need to be accessible across multiple components within the same web application.
websocket:
This is used as part of socket programming. We can’t use in our Servlet based MVC
application level.
In Java Spring, the @Configuration annotation is used to indicate that this class is a
configuration class of Beans. A configuration class is responsible for defining beans and their
dependencies in the Spring application context. Beans are objects that are managed by the
Spring IOC container. Annotating a class with the @Configuration indicates that the class can
be used by the Spring IOC container as a source of bean definitions.
Create a Java class and annotate it with @Configuration. This class will serve as our
configuration class.
@Bean:
• Now Create a Project and add below jars to support Spring Annotations of Core Module.
NOTE: Added one extra jar file comparing with previous project setup. Because internally
Spring core module using AOP functionalities to process annotations.
package com.amazon.users;
Now Create a Beans Configuration class. i.e. Class Marked with an annotation
@Configuration. In side this configuration class, we will define multiple bean configurations
with @Bean annotation methods.
package com.amazon.config;
@Configuration
public class BeansConfiguration {
@Bean("userDetails")
UserDetails getUserDetails() {
return new UserDetails();
}
}
The above code will be equivalent to the following XML bean configuration –
<beans>
<bean id = "userDetails" class = "com.amazon.users.UserDetails" />
</beans>
package com.amazon;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import com.amazon.config.BeansConfiguration;
import com.amazon.users.UserDetails;
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext(BeansConfiguration.class);
Now we can configure multiple bean classes inside multiple configuration classes as well
as Same bean with multiple bean id’s.
package com.amazon.products;
Configuring above POJO class as Bean class inside Beans Configuration class.
package com.amazon.config;
import org.springframework.context.annotation.Bean;
import com.amazon.products.ProductDetails;
@Bean("productDetails")
ProductDetails productDetails() {
return new ProductDetails();
}
}
➢ Testing Bean Object Created or not. Below Code loading Two Configuration classes.
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import com.amazon.config.BeansConfiguration;
import com.amazon.config.BeansConfigurationTwo;
import com.amazon.products.ProductDetails;
import com.amazon.users.UserDetails;
public class SpringBeanMainApp {
AnnotationConfigApplicationContext context
= new AnnotationConfigApplicationContext();
➢ Inside Configuration class: Two Bean configurations for ProductDetails Bean class.
import org.springframework.context.annotation.Bean;
import com.amazon.products.ProductDetails;
@Bean("productDetails")
ProductDetails productDetails() {
return new ProductDetails();
}
@Bean("productDetailsTwo")
ProductDetails productTwoDetails() {
return new ProductDetails();
}
}
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import com.amazon.config.BeansConfiguration;
import com.amazon.config.BeansConfigurationTwo;
import com.amazon.products.ProductDetails;
import com.amazon.users.UserDetails;
context.register(BeansConfiguration.class);
context.register(BeansConfigurationTwo.class);
context.refresh();
Output:
com.amazon.users.UserDetails@7d3e8655
com.amazon.products.ProductDetails@7dfb0c0f
com.amazon.products.ProductDetails@626abbd0
From above Output Two ProductDetails bean objects created by Spring Container.
@Component Annotation :
@Component: This annotation that allows Spring to detect our custom beans automatically.
In other words, without having to write any explicit code, Spring will:
We have other more specialized stereotype annotations like @Controller, @Service and
@Repository to serve this functionality derived , we will discuss then in MVC module level.
package com.tek.teacher;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@Component
public class Product {
public Product(){
System.out.println(“Product Object Created.”);
}
public String getPname() {
return pname;
}
public void setPname(String pname) {
this.pname = pname;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
}
context.scan("com.tek. teacher");
context.refresh();
From Above program, context.scan() method, Perform a scan for @Component classes to
instantiate Bean Objects within the specified base packages. We can pass many package
names wherever we have @Componet Classes. Note that, scan(basePackages) method will
scans @Confguraion classes as well from specified package names. Note that refresh() must
be called in order for the context to fully process the new classes.
Spring Provided One more way which used mostly in Real time applications is using
@ComponentScan annotation. To enable auto detection of Spring components, we shou use
another annotation @ComponentScan.
@ComponentScan:
Before we rely entirely on @Component, we must understand that it's only a plain
annotation. The annotation serves the purpose of differentiating beans from other objects,
such as domain objects. However, Spring uses the @ComponentScan annotation to gather all
component into its ApplicationContext.
@ComponentScan annotation is used to specify packages for spring to scan for
annotated components. Spring needs to know which packages contain beans, otherwise you
would have to register each bean individually. Hence @ComponentScan annotation is a
supporting annotation for @Configuration annotation. Spring instantiate Bean Objects of
components from specified packages for those classes annotated with @Component.
So create a beans configuration class i.e. @Configuration annotated class and provide
@ComponentScan with base package name.
Ex: When we have to scan multiple packages we can pass all package names as String array
with attribute basePackages.
@ComponentScan(basePackages =
{"com.hello.spring.*","com.hello.spring.boot.*"})
@Configuration
//making sure scanning all packages starts with com.tek.teacher
@ComponentScan("com.tek.teacher.*")
public class BeansConfiguration {
➢ Now Load/pass above configuration class to Application Context i.e. Spring Container.
package com.tek.teacher;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
From above, Spring Container detected @Component classes from all packages and
instantiated as Bean Objects.
package com.tek.teacher;
import org.springframework.stereotype.Component;
public UserDetails(){
System.out.println(“UserDetails Object Created”);
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getEmailId() {
return emailId;
}
public void setEmailId(String emailId) {
this.emailId = emailId;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public long getMobile() {
return mobile;
}
public void setMobile(long mobile) {
this.mobile = mobile;
}
}
➢ Now get UserDetails from Spring Container and Test/Run our Main class.
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
context.register(BeansConfiguration.class);
context.refresh();
//UserDetails Component
UserDetails userDetails = context.getBean(UserDetails.class);
System.out.println(userDetails);
}
}
Output: com.tek.teacher.UserDetails@5e17553a
We can use any of overloaded method getBean() to get Bean Object as per our requirement
or functionality demanding.
Ex : From above example, requesting another Bean Object of type UserDetails without
configuring scope at component class level.
package com.tek.teacher;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
// UserDetails Component
So we can say by default component classes are instantiated as singleton bean object, when
there is no scope defined. Means, Internally Spring Container considering as singleton scope.
package com.tek.teacher;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan("com.tek.*")
public class BeansConfiguration {
@Bean("user")
UserDetails getUserDetails() {
return new UserDetails();
}
}
package com.tek.teacher;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
// UserDetails Component
UserDetails userThree = (UserDetails) context.getBean("user");
System.out.println(userThree);
}
}
Output: com.tek.teacher.UserDetails@3eb91815
We can pass/initialize default values to a component class instance with @Bean method
implementation inside Spring Configuration classes.
package com.tek.teacher;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan("com.tek.*")
public class BeansConfiguration {
@Bean("user")
UserDetails getUserDetails() {
UserDetails user = new UserDetails();
user.setEmailId("dilip@gmail.com");
user.setMobile(8826111377l);
return user;
}
}
Main App:
package com.tek.teacher;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
// UserDetails Component
UserDetails userThree = (UserDetails) context.getBean("user");
System.out.println(userThree.getEmailId());
System.out.println(userThree.getMobile());
}
}
Output:
dilip@gmail.com
8826111377
In XML configuration, we will use an attribute “scope”, inside <bean> tag as shown below.
@Scope: A bean’s scope is set using the @Scope annotation. By default, the Spring
framework creates exactly one instance for each bean declared in the IoC container. This
instance is shared in the scope of the entire IoC container and is returned for all subsequent
getBean() calls and bean references.
Example: Create a bean class and configure with Spring Container : ProductDetails.java
package com.amazon.products;
Now Inside Configuration class, Define Bean Creation and Configure scope value.
Singleton Scope:
A single Bean object instance created and returns same Bean instance for each Spring IoC
container call i.e. getBean(). In side Configuration class, scope value defined as singleton.
NOTE: If we are not defined any scope value for any Bean Configuration, then Spring
Container by default considers scope as singleton.
package com.amazon.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
import com.amazon.products.ProductDetails;
@Configuration
public class BeansConfigurationThree {
@Scope("singleton")
@Bean("productDetails")
ProductDetails getProductDetails() {
return new ProductDetails();
}
}
➢ Now Test Bean ProdcutDetails Object is singleton or not. Request multiple times
ProductDetails Object from Spring Container by passing bean id productDetails.
package com.amazon;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import com.amazon.config.BeansConfigurationThree;
import com.amazon.products.ProductDetails;
Output:
com.amazon.products.ProductDetails@58e1d9d
com.amazon.products.ProductDetails@58e1d9d
From above output, we can see same hash code printed for both getBean() calls on Spring
Container. Means, Container created singleton instance for bean id “productDetails”.
package com.amazon.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
import com.amazon.products.ProductDetails;
@Configuration
public class BeansConfigurationThree {
@Scope("singleton")
@Bean("productDetails")
ProductDetails getProductDetails() {
return new ProductDetails();
}
@Scope("prototype")
@Bean("productTwoDetails")
ProductDetails getProductTwoDetails() {
return new ProductDetails();
}
}
➢ Now Test Bean ProdcutDetails Object is prototype or not. Request multiple times
ProductDetails Object from Spring Container by passing bean id productTwoDetails.
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import com.amazon.config.BeansConfigurationThree;
import com.amazon.products.ProductDetails;
Output:
com.amazon.products.ProductDetails@12591ac8
com.amazon.products.ProductDetails@5a7fe64f
From above output, we can see different hash codes printed for both getBean() calls on Spring
Container. Means, Container created new instance every time when we requested for
instance of bean id “productTwoDetails”.
If we are not passed any scope value via @Scope annotation to a component class, then
Component Bean Object will be created as singleton as usually.
@Scope("prototype")
@Component
public class UserDetails {
//Properties
//Setter & Getters
// Methods
}
Now test from Main application class, whether we are getting new Instance or not for every
request of Bena Object UserDetails from Spring Container.
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
// UserDetails Component
UserDetails userDetails = context.getBean(UserDetails.class);
System.out.println(userDetails);
Output:
com.tek.teacher.UserDetails@74f6c5d8
com.tek.teacher.UserDetails@27912e3
NOTE: Below four are available only if you use a web-aware ApplicationContext i.e. inside
Web applications.
➢ request
➢ session
➢ application
➢ globalsession
➢ no
➢ byName
➢ byType
➢ constructor
In XML configuration, we will enable auto wring between Beans as shown below.
1. On properties
2. On setter
3. On constructor
@Autowired on Properties
Let’s see how we can annotate a property using @Autowired. This eliminates
the need for getters and setters.
package com.dilip.account;
import org.springframework.stereotype.Component;
Now Define, Another component class Account and define Address type property inside as a
Dependency property.
package com.dilip.account;
import org.springframework.beans.factory.annotation.Autowired;
@Component
public class Account {
// Field/Property Level
@Autowired
private Address addr;
package com.dilip.account;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan("com.dilip.*")
public class BeansConfiguration {
➢ Now Define, Main class and try to get Account Bean object and check really Address
Bean Object Injected or Not.
package com.dilip.account;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
// UserDetails Component
Account account = (Account) context.getBean(Account.class);
//Getting Injected Object of Address
Address address = account.getAddr();
address.setPincode(500072);
So, Dependency Object Address injected in Account Bean Object implicitly, with @Autowired
on property level.
package com.hello.spring.boot.employees;
import org.springframework.stereotype.Component;
@Component("home")
public class Addresss {
➢ For above Address class create a Bean configuration in Side Configuration class.
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan("com.hello.spring.boot.*")
public class BeansConfig {
@Bean("hyd")
Addresss createAddress() {
Addresss a = new Addresss();
a.setPincode(500067);
a.setStreetName("Gachibowli");
return a;
}
}
package com.hello.spring.boot.employees;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
@Component("emp")
public class Employee {
@Autowired
private Addresss add;
➢ Now Test which Address Object Injected by Container i.e. either home or hyd bean
object.
package com.hello.spring.boot.employees;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
i.e. Spring Container unable to inject Address Bean Object into Employee Object because of
Ambiguity/Confusion like in between home or hyd bean Objects of Address type.
We need to take into consideration that the qualifier name to be used is the one declared in
the @Component or @Bean annotation.
package com.hello.spring.boot.employees;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
@Component("emp")
public class Employee {
@Qualifier("hyd")
@Autowired
private Addresss add;
➢ Now Test which Address Bean Object with bean Id “hyd” Injected by Container.
package com.hello.spring.boot.employees;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext();
context.register(BeansConfig.class);
context.refresh();
Employee empployee = (Employee) context.getBean("emp");
Addresss empAdd = empployee.getAdd();
System.out.println(empAdd.getPincode());
System.out.println(empAdd.getStreetName());
}
}
Output: 500067
Gachibowli
i.e. Address Bean Object Injected with Bean Id called as hyd into Employee Bean Object.
@Primary:
There's another annotation called @Primary that we can use to decide which bean to
inject when ambiguity is present regarding dependency injection. This annotation defines a
preference when multiple beans of the same type are present. The bean associated with
the @Primary annotation will be used unless otherwise indicated.
Now add One more @Bean config for Address class inside Configuration class.
package com.hello.spring.boot.employees;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
@Configuration
@ComponentScan("com.hello.spring.boot.*")
public class BeansConfig {
@Bean("hyd")
package com.hello.spring.boot.employees;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
@Component("emp")
public class Employee {
Output:
560043
Banglore
I.e. Address Bean Object with “banglore" injected in Employee object level.
NOTE: if both the @Qualifier and @Primary annotations are present, then
the @Qualifier annotation will have precedence/priority. Basically, @Primary defines a
default, while @Qualifier is very specific to Bean ID.
In Java, Interface reference can hold Implemented class Object. With this rule, We can
Autowire Interface references to inject implemented component classes.
package com.dilip.auto.wiring;
package com.dilip.auto.wiring;
import org.springframework.stereotype.Component;
@Component
public class Tiger implements Animal {
@Override
public void printNameOfAnimal() {
System.out.println("I am a Tiger ");
}
}
package com.dilip.auto.wiring;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan("com.dilip.*")
public class BeansConfig {
➢ Now Autowire Animal type property in any other Component class i.e. Dependency of
Animal Interface implemented class Object Tiger should be injected.
package com.dilip.auto.wiring;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class AnimalManagement {
@Autowired
//Interface Type Property
Animal animal;
➢ Now Test, Animal type property injected with what type of Object.
package com.dilip.auto.wiring;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
Output: I am a Tiger
So, implicitly Spring Container Injected one and only implanted class Tiger of Animal Interface
inside Animal Type reference property of AnimalManagement Object.
If we have multiple Implemented classes for same Interface i.e. Animal interface, How
Spring Container deciding which implanted Bean object should Injected?
package com.dilip.auto.wiring;
import org.springframework.stereotype.Component;
@Component("lion")
public class Lion implements Animal {
@Override
public void printNameOfAnimal() {
System.out.println("I am a Lion ");
}
}
➢ Now Test, Animal type property injected with what type of Object either Tiger or Lion.
package com.dilip.auto.wiring;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext();
context.register(BeansConfig.class);
context.refresh();
So to avoid this ambiguity again between multiple implementation of single interface, again
we can use @Qualifier with Bean Id or Component Id.
package com.dilip.auto.wiring;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
@Component
public class AnimalManagement {
@Qualifier("lion")
@Autowired
Animal animal;
}
Now it will inject only Lion Object inside AnimalManagement Object as per @Qualifier
annotation value out of lion and tiger bean objects.
Output : I am a Lion.
Can we inject Default implemented class Object out of multiple implementation classes
into Animal reference if not provided any Qualifier value?
Yes, we can inject default Implementation bean Object of Interface. We should mark one class
as @Primary. Now I marked Tiger class as @Primary and removed @Qualifier from
AnimalManagement.
package com.dilip.auto.wiring;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class AnimalManagement {
@Autowired
Animal animal;
}
Output : I am a Tiger
Filed Injection:
As the name says, the dependency is injected directly in the field, with no constructor
or setter needed. This is done by annotating the class member with the @Autowired
annotation. If we define @Autowired on property/field name level, then Spring Injects
Dependency Object directly into filed.
package com.dilip.spring;
import org.springframework.stereotype.Component;
@Component
public class Address {
public Address() {
System.out.println("Address Object Created.");
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public int getPincode() {
return pincode;
}
public void setPincode(int pincode) {
this.pincode = pincode;
}
}
package com.dilip.spring;
@Component
public class Employee {
//Field Injection
@Autowired
private Address address;
We are Defined @Autowired on Address type field in side Employee class, So Spring IOC will
inject Address Bean Object inside Employee Bean Object via field directly.
Testing DI:
package com.dilip.spring;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
Setter injection uses the setter method to inject dependency on any Spring-managed
bean. Well, the Spring IOC container uses a setter method to inject dependency on any Spring-
managed bean. We have to annotate the setter method with the @Autowired annotation.
Interface : MessageService.java
package com.dilip.setter.injection;
package com.dilip.setter.injection;
import org.springframework.stereotype.Component;
@Component("emailService")
public class EmailService implements MessageService {
@Override
public void sendMessage(String message) {
System.out.println(message);
}
}
package com.dilip.setter.injection;
import org.springframework.stereotype.Component;
@Component("smsService")
public class SMSService implements MessageService {
@Override
public void sendMessage(String message) {
System.out.println(message);
}
}
We have annotated SMSService class with @Component annotation so the Spring container
automatically creates a Spring bean and manages its life cycle.
MessageSender.java: In setter injection, Spring will find the @Autowired annotation and
call the setter method to inject the dependency.
package com.dilip.setter.injection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
@Component
public class MessageSender {
➢ Now create a Test class to validate, dependency injection with setter Injection.
package com.dilip.setter.injection;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
Output:
setter based dependency injection
Hi, good morning have a nice day!.
Let's see how to inject multiple dependencies using Setter injection. To inject multiple
dependencies, we have to create multiple fields and their respective setter methods. In the
below example, the MessageSender class has multiple setter methods to inject multiple
dependencies using setter injection:
package com.dilip.setter.injection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
@Component
public class MessageSender {
@Autowired
public void setSmsService(MessageService smsService) {
this.smsService = smsService;
System.out.println("setter based dependency injection 2");
}
Output:
setter based dependency injection 2
setter based dependency injection
Hi, good morning have a nice day!.
Hi, good morning have a nice day!.
Constructor Injection:
package com.dilip.setter.injection;
➢ EmailService.java
package com.dilip.setter.injection;
import org.springframework.stereotype.Component;
@Component
public class EmailService implements MessageService {
@Override
public void sendMessage(String message) {
System.out.println(message);
}
}
We have annotated EmailService class with @Component annotation so the Spring container
automatically creates a Spring bean and manages its life cycle.
➢ SMSService.java
package com.dilip.setter.injection;
import org.springframework.stereotype.Component;
@Component("smsService")
public class SMSService implements MessageService {
@Override
public void sendMessage(String message) {
System.out.println(message);
}
}
We have annotated SMSService class with @Component annotation so the Spring container
automatically creates a Spring bean and manages its life cycle.
package com.dilip.setter.injection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;
@Component
public class MessageSender {
package com.dilip.setter.injection;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan(basePackages = "com.dilip.*")
public class AppConfig {
➢ Now create a Test class to validate, dependency injection with setter Injection.
package com.dilip.setter.injection;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
ApplicationContext applicationContext =
new AnnotationConfigApplicationContext(AppConfig.class);
MessageSender messageSender =
applicationContext.getBean(MessageSender.class);
messageSender.sendMessage(message);
}
}
Output:
constructor based dependency injection
Hi, good morning have a nice day!.
When we discussed of autowiring with beans XML configurations, Spring Provided 4 types
autowiring configuration values for autowire attribute of bean tag.
1. no
2. byName
3. byType
4. constructor
But with annotation Bean configurations, we are not using these values directly because we
are achieving same functionality with @Autowired and @Qualifier annotations directly or
indirectly.
So explicitly we no need to define any autowiring type with annotation based Configurations
like in XML configuration.
The Spring Bean life cycle is the heartbeat of any Spring application, dictating how
beans are created, initialized, and eventually destroyed. The lifecycle of any object means
when & how it is born, how it behaves throughout its life, and when & how it dies. Similarly,
the bean life cycle refers to when & how the bean is instantiated, what action it performs
until it lives, and when & how it is destroyed.
Spring bean is a Java object managed by the Spring IoC container. These objects can
be anything, from simple data holders to complex business logic components. The magic lies
in Spring’s ability to manage the creation, configuration, and lifecycle of these beans.
Bean life cycle is managed by the spring container. When we run the program then,
first of all, the spring container gets started. After that, the container creates the instance of
a bean as per configuration, and then dependencies are injected. After utilization of Bean
Object and then finally, the bean is destroyed when the spring container is closed.
Therefore, if we want to execute some code on the bean instantiation and just after
closing the spring container, then we can write that code inside the custom init() method and
the destroy() methods.
➢ Resource Management: As you traverse the life cycle stages of Bean Object, you’re in
control of resources. This translates to efficient memory utilization and prevents resource
leaks, ensuring your application runs like a well configured machine.
➢ Customization: By walking through the life cycle stages, you can inject custom logic at
strategic points. This customization allows your beans to adapt to specific requirements,
setting the stage for a flexible and responsive application.
➢ Dependency Injection: Understanding the stages of bean initialization also resolves the
magic of dependency injection. You’ll learn how beans communicate, collaborate, and
share information, building a cohesive application architecture.
➢ Debugging: With a firm grasp of the life cycle, troubleshooting becomes very easy. By
tracing a bean’s journey through each stage, you can pinpoint issues and enhance the
overall stability of your application.
Spring allows us to attach custom actions to bean creation and destruction. We can
do it by implementing the InitializingBean and DisposableBean interfaces.
InitializingBean:
When the Spring container initializes the Bean instance, it will first set any properties
configured, and then it will call the afterPropertiesSet() method automatically. This allows
you to perform any custom initialization tasks within that method.
DisposableBean:
The DisposableBean interface defines a single method, destroy(), which a bean class
must implement to carry out any cleanup logic.
When the Spring container is shutting down or removing the bean, it will call the destroy()
method automatically, allowing you to perform any necessary cleanup tasks.
package com.dilip;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.stereotype.Component;
@Component
public class Customer implements InitializingBean, DisposableBean {
public Customer() {
System.out.println("Customer Object is Created");
}
The following image shows the process flow of the Bean Object life cycle.
package com.dilip;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@ComponentScan("com.dilip")
@Configuration
public class BeansConfiguration {
package com.dilip;
import
org.springframework.context.annotation.AnnotationConfigApplicationContext;
Output:
➢ Adding a Bean Method inside Configuration class for another Customer Object and then
we will see same process followed for new Bean Object as usually.
BeansConfiguration.java
package com.dilip;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@ComponentScan("com.dilip")
@Configuration
public class BeansConfiguration {
@Bean(name="customer2")
Customer getCustomer() {
return new Customer();
}
}
➢ Now Execute container creation and closing Lofigc again and observe initialization and
destroy methods executed 2 times for 2 Customer Bean Objects creation.
package com.dilip;
import
org.springframework.context.annotation.AnnotationConfigApplicationContext;
Output : For Every bean Object, executed both actions of initialization and destroy.
This is how we can define lifecycle methods explicitly to provide instantiation logic and
destruction logic for a bean Object.
Note: Same above approach of writing Bean class with InitializingBean and DisposableBean,
can be followed in Spring Beans XML configuration for a Bean class and Objects.
Question: Do we have any other ways to define life cycle methods apart from
InitializingBean and DisposableBean?
Note: Both @PostConstruct and @PreDestroy annotations are part of Java EE. Since Java EE
was deprecated in Java 9, and removed in Java 11, we have to add an additional dependency
in pom.xml to use these annotations.
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<version>1.3.2</version>
</dependency>
@PostConstruct:
Spring calls the methods annotated with @PostConstruct only once, just after the
initialization of bean properties i.e. this is a replacement of InitializingBean and its associated
abstract method implementation.
@PreDestroy:
Spring calls the methods annotated with @PreDestroy runs only once, just before
Spring removes our bean from the application context.
Note: @PostConstruct and @PreDestroy annotated methods can have any access level, but
can’t be static.
package com.dilip;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import org.springframework.stereotype.Component;
@Component
public class Customer {
public Customer() {
System.out.println("Customer Object is Created");
}
@PostConstruct
public void init() {
System.out.println("This is Init logic from init()");
}
@PreDestroy
public void destroy() {
System.out.println("This is destroying logic from destroy()");
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
package com.dilip;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@ComponentScan("com.dilip")
@Configuration
public class BeansConfiguration {
@Bean(name="customer2")
Customer getCustomer() {
return new Customer();
}
}
➢ Now Execute container creation and closing Lofigc again and observe initialization and
destroy methods executed 2 times for 2 Customer Bean Objects creation.
package com.dilip;
import
org.springframework.context.annotation.AnnotationConfigApplicationContext;
Question: Can we define custom methods in class for initialization and destruction of a bean
object i.e. without using Pre-Defined Interfaces and Annotations ?
Yes, We can Define custom methods with user defined names of methods of both initialization
and destroying actions.
package com.dilip;
public Student() {
System.out.println("Student Constructor : Object Created");
}
public int getSid() {
return sid;
}
public void setSid(int sid) {
this.sid = sid;
}
// For Initialization
public void beanInitialization() {
System.out.println("Bean Initialization Started... ");
}
// For Destruction
public void beanDestruction() {
System.out.println("Bean Destruction Started..... ");
}
}
In XML Configuration :
<beans>
<bean id="student" class="com.dilip.Student"
init-method="beanInitialization"
destroy-method="beanDestruction">
</bean>
</beans>
➢ Now Instantiate and close Spring Container and then container will execute life cycle
methods as per our configuration of a bean Object.
Understanding the life cycle of Spring beans is like having a backstage pass to the inner
workings of your Spring application. A solid grasp of the bean life cycle empowers you to
effectively manage resources, configure beans, and ensure proper initialization and cleanup.
With this knowledge, you can optimize your application’s performance, prevent memory
leaks, and implement custom logic at various stages of a bean’s existence.