Bean lifecycle refers to the collective information of a bean object right from its starting point to the ending point in the Spring Applications.
In Spring Applications, Bean lifecycle has the following steps.
- Bean Loading
- Bean Instantiation
- Bean Initialization
- Bean Destruction
Bean Loading
In Spring applications, when we provide bean class configuration in the Spring configuration file and when we create an ApplicationContext object , automatically ApplicationContext will recognize all the bean classes and it will perform loading of all the bean classes in order to create bean objects.
In the Spring Framework, loading beans involves creating and configuring instances of Java objects (beans) as defined in the Spring container configuration.
Spring provides several ways to load beans, including :
- XML-based configuration
- Annotation-based configuration, and
- Java-based configuration.
In XML-based configuration, you define beans and their dependencies in an XML file (e.g., applicationContext.xml). Spring loads this XML file during application startup and creates the beans defined in it.
With annotation-based configuration, you use annotations such as @Component, @Service, @Repository, and @Autowired to define beans and their dependencies directly in Java classes. Spring scans your application’s classpath for annotated components during startup, identifies the components annotated with @Service and @Repository, and automatically creates beans for them along with their dependencies.
Java-based configuration involves defining beans and their dependencies using Java configuration classes annotated with @Configuration and @Bean. You define methods in the configuration class that return instances of beans, and Spring uses these methods to create beans. During application startup, Spring loads the configuration class and creates beans based on the @Bean-annotated methods.
Bean Instantiation
In Spring applications, after loading all the bean classes, ApplicationContext will create objects for all the bean classes.
In Spring applications, there are three ways to perform bean Instantiation.
- Bean Instantiation through Constructors
- Bean Instantiation through Static Factory Method
- Bean Instantiation through an Instance Factory method
Bean Instantiation through Constructors
In Spring applications, ApplicationContext containers will create bean objects by using the default constructor or 0-arg constructor internally.
In Spring applications, we are able to create bean objects by using our own constructors also through the ApplicationContext.
If we want to execute a parameterized constructor while performing Bean Instantiation then we have to configure the constructor parameters in the spring configuration file.
To configure the constructor parameters in the spring configuration file we have to use the following xml tags.
<beans>
<bean name=”emp” class=”com.durgasoft.beans.Employee”>
<constructor-arg value=”111”/>
<constructor-arg value=”Durga”/>
<constructor-arg value=”50000”/>
<constructor-arg value=”Hyd”/>
</bean>
</beans>
Example
Employee.java
package com.durgasoft.beans;
public class Employee {
private int eno;
private String ename;
private float esal;
private String eaddr;
public Employee(int eno, String ename, float esal, String eaddr) {
this.eno = eno;
this.ename = ename;
this.esal = esal;
this.eaddr = eaddr;
System.out.println("Bean Instantiation.......");
}
public void getEmployeeDetails(){
System.out.println("Employee Details");
System.out.println("------------------------");
System.out.println("Employee Number : "+eno);
System.out.println("Employee Name : "+ename);
System.out.println("Employee Salary : "+esal);
System.out.println("Employee Address : "+eaddr);
}
}
Spring-Config.xml
<?xml version="1.0" encoding="UTF-8"?>
<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 name="employee" class="com.durgasoft.beans.Employee">
<constructor-arg value="111"/>
<constructor-arg value="Durga"/>
<constructor-arg value="50000.0"/>
<constructor-arg value="Hyd"/>
</bean>
</beans>
Main.java
import com.durgasoft.beans.Employee;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("Spring-Config.xml");
Employee employee = (Employee) applicationContext.getBean("employee");
employee.getEmployeeDetails();
}
}
Bean Instantiation through a static Factory Method
If any static method returns either the same class object or some other class object then that static method is a Static Factory method.
If we want to create a bean object by using a static factory method then we have to use the following steps.
- Create a Bean class with the required properties and setters and getters.
- Declare a static factory method in the same bean class.
- In the Spring configuration file , configure the static factory method by using the “
factory-method” attribute in the <bean> tags. - Create a Test application to test the static factory method based bean instantiation.
Example
Hello.java
package com.durgasoft.beans;
public class Hello {
public Hello() {
System.out.println("Hello Bean Instantiation......");
}
public static Hello getInstance(){
System.out.println("Bean instantiation through static factory method");
Hello hello = new Hello();
return hello;
}
public String sayHello(){
return "Hello User!";
}
}
Spring-Config.xml
<?xml version="1.0" encoding="UTF-8"?>
<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 name="hello" class="com.durgasoft.beans.Hello" factory-method="getInstance"/>
</beans>
Main.java
import com.durgasoft.beans.Hello;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("Spring-Config.xml");
Hello hello = (Hello)applicationContext.getBean("hello");
System.out.println(hello.sayHello());
}
}
Bean Instantiation through an Instance Factory method
If any instance method returns an object then that instance method is called an Instance Factory method.
To create bean objects by using the instance factory method , we have to use the following steps.
- Create a Bean class with the required properties and setXXX() and getXXX() methods.
- Create a Factory class with the instance factory method to return the respective Bean object.
- Provide Spring configuration file with the following configurations.
- Configure Factory class as a bean.
- Configure Bean class with factory-bean and factory-method attributes by providing Factory class reference and the factory method.
- Prepare a test application to test the instance Factory method.
Example :
Hello.java
package com.durgasoft.beans;
public class Hello {
public Hello() {
System.out.println("Hello Bean Instantiation......");
}
public String sayHello(){
return "Hello User!";
}
}
HelloFactory.java
package com.durgasoft.factory;
import com.durgasoft.beans.Hello;
public class HelloFactory {
public Hello getHelloInstance(){
System.out.println("from getHelloInstance() method");
return new Hello();
}
}
Spring-Config.xml
<?xml version="1.0" encoding="UTF-8"?>
<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 name="helloFactory" class="com.durgasoft.factory.HelloFactory"/>
<bean name="hello" class="com.durgasoft.beans.Hello" factory-bean="helloFactory" factory-method="getHelloInstance"/>
</beans>
Main.java
import com.durgasoft.beans.Hello;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("Spring-Config.xml");
Hello hello = (Hello)applicationContext.getBean("hello");
System.out.println(hello.sayHello());
}
}
Bean Initialization and Bean Destruction
In spring applications, after creating bean objects by the ApplicationContext Container, the applicationContext container has to provide initialization inside the bean objects.
In the Spring applications, after the business logic execution , we have to destroy the bean objects.
In Spring applications, to perform bean initialization and the Bean destruction we have to use the following approaches.
- By Using Custom Bean initialization and Destructor methods.
- By Implementing InitializingBean and DisposableBean callback interfaces.
- By using @PostConstruct and @Predestroy annotations
Using Custom Bean initialization and Destructor methods:
In this approach, we will define our own methods for initialization and destruction of the bean objects and we have to configure them in the Spring configuration file by using “init-method” and “destroy-method” attributes in the bean definition.
public class Hello{
—---
public void init(){
System.out.println(“Custom Initialization Method”);
}
public void destroy(){
System.out.println(“Custom Destruction Method”);
}
}
<beans>
<bean name=”hello” class=”com.durgasoft.beans.Hello”
init-method=”init” destroy-method=”destroy”/>
</beans>
Note: In the Test Application, use AbstractApplicationContext abstract class in place of ApplicationContext interface to show the Bean object destruction process, because ApplicationContext interface has not provided methods to start, stop, refresh and destroy the container, AbstractApplicationContext has provided the methods like start(), stop(), refresh() and registerShutdownHook() to start, to stop , to refresh and to shutdown the container.
Hello.java
package com.durgasoft.beans;
public class Hello {
static{
System.out.println("Bean Loading");
}
public Hello(){
System.out.println("Bean Instantiation");
}
public void init(){
System.out.println("Bean Initialization : Custom Initialization Method");
}
public void destroy(){
System.out.println("Bean Destruction : Custom destruction Method");
}
public String sayHello(){
return "Hello User!";
}
}
Spring-Config.xml
<?xml version="1.0" encoding="UTF-8"?>
<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 name="hello" class="com.durgasoft.beans.Hello" init-method="init" destroy-method="destroy"/>
</beans>
Main.java
import com.durgasoft.beans.Hello;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main {
public static void main(String[] args) {
//ApplicationContext applicationContext = new ClassPathXmlApplicationContext("Spring-Config.xml");
AbstractApplicationContext applicationContext = new ClassPathXmlApplicationContext("Spring-Config.xml");
Hello hello = (Hello)applicationContext.getBean("hello");
System.out.println(hello.sayHello());
applicationContext.registerShutdownHook();
}
}
In the above example, we have specified the init and destroy methods specific to the bean. However, we can even specify the default init and destroy methods for all the beans.
Spring-Config.xml
<?xml version="1.0" encoding="UTF-8"?>
<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"
default-init-method="init" default-destroy-method="destroy"
>
<bean name="hello" class="com.durgasoft.beans.Hello" />
<bean name="wish" class="com.durgasoft.beans.Wish" />
<bean name="welcome" class="com.durgasoft.beans.Welcome" />
</beans>
Output :
Hello Bean Loading
Hello Bean Instantiation
Hello Bean Initialization : Custom Initialization Method
Wish Bean Loading
Wish Bean Instantiation
Wish Bean Initialization: Custom Initialization Method
Welcome Bean Loading
Welcome Bean Instantiation
Welcome Bean Initialization: Custom Initialization Method
Hello User!
Hello User, Good Morning!
Hello User, Welcome to Durgasoft!
Welcome Bean Destruction : Custom Destruction Method
Wish Bean Destruction : Custom Destruction Method
Hello Bean Destruction : Custom destruction Method
Implementing InitializingBean and DisposableBean callback interfaces:
InitializingBean is an interface , it has provided the following method to execute in order to perform Bean initialization.
public void afterPropertiesSet()
DisposableBean is an interface , it has provided the following method to execute in order to perform Bean Destruction.
public void destroy()
In Spring applications, to use InitializingBean and DisposableBean interfaces we have to implement these interfaces in the bean class and we must provide implementation to the respective methods.
In the above context, afterPropertiesSet() method will be executed when the bean initialization is performed by the IOC Container, destroy() method will be executed when the bean destruction is performed by the IOC Container.
Hello.java
package com.durgasoft.beans;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
public class Hello implements InitializingBean, DisposableBean {
static{
System.out.println("Hello Bean Loading....");
}
public Hello(){
System.out.println("Hello Bean Instantiation.....");
}
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("Hello Bean init: InitializingBean interface");
}
public String sayHello(){
return "Hello User!";
}
@Override
public void destroy() throws Exception {
System.out.println("Hello Bean Destroy : DisposableBean interface");
}
}
Spring-Config.xml
<?xml version="1.0" encoding="UTF-8"?>
<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 name="hello" class="com.durgasoft.beans.Hello"/>
</beans>
Main.java
import com.durgasoft.beans.Hello;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main {
public static void main(String[] args) {
AbstractApplicationContext applicationContext = new ClassPathXmlApplicationContext("Spring-Config.xml");
Hello hello = (Hello) applicationContext.getBean("hello");
System.out.println(hello.sayHello());
applicationContext.registerShutdownHook();
}
}
Output :
Hello Bean Loading....
Hello Bean Instantiation.....
Hello Bean Initialization : InitializingBean interface
Hello User!
Hello Bean Destruction : DisposableBean interface
Using @PostConstruct and @Predestroy
If we provide any method with @PostConstruct annotation then that method will be executed at the time of performing Bean Initialization.
If we provide any method with @Predestroy annotation then that method will be executed at the time of performing Bean Destruction.
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
public class Hello{
static{
System.out.println("Hello Bean Loading....");
}
public Hello(){
System.out.println("Hello Bean Instantiation.....");
}
@PostConstruct
public void init(){
System.out.println("Hello Bean Initialization : @PostConstructor");
}
@PreDestroy
public void destroy(){
System.out.println("Hello Bean Destruction : @PreDestroy");
}
public String sayHello(){
return "Hello User!";
}
}
Note:The latest Spring Framework does not support the @PostConstruct and @Predestroy annotations , these annotations are outdated annotations.
In general, in the Spring applications, we will use either of the above mechanisms for the bean initialization and bean destruction, but if we provide all the above three mechanisms at a time in a single bean then in the following order all the bean initializations are performed.
Output :
Initialization Order
Hello Bean Initialization : @PostConstreuct[If it is supported]
Hello Bean Initialization : IntializingBean
Hello Bean Initialization : Custom Initialization Method
Destruction Order
Hello Bean Destruction : @PreDestroy[If it is supported]
Hello Bean Destruction : DisposableBean
Hello Bean Destruction : Custom Destruction Method
Bean Inheritance
In Spring applications, we will provide more number of bean classes as per the required, with this we must provide more number of bean configurations in the spring configuration file, under every bean configuration we have to provide number of configurations like properties configurations, constructor-arg configurations, dependency injections, initialization and destruction methods configurations,….. as per the requirement.
In some situations, we may have the same configurations in more than one bean definition, it represents configurations redundancy, it is not suggestible in the applications, here to optimize the configurations we have to provide configurations reusability from one bean definition to the another bean definition like code reusability from one java class to another java class by using inheritance relationship in Java.
In the above context, to reuse one bean definition provided configurations in the another bean definition by extending one bean definition to another bean definition with the “parent” attribute in the child bean definition.
<beans>
<bean name=”bean1” class=”com.dss.beans.Bean1”>
—-----
</bean>
<bean name=”bean2” class=”com.dss.beans.Bean2” parent=”bean1” >
All configurations of bean1 available here, either reuse/override
</bean>
</beans>
EX:
Wish.java
package com.durgasoft.beans;
public class Wish {
private String name;
private String wishMessage;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getWishMessage() {
return wishMessage;
}
public void setWishMessage(String wishMessage) {
this.wishMessage = wishMessage;
}
public String sayWish(){
return wishMessage+" "+name;
}
}
Hello.java
package com.durgasoft.beans;
public class Hello {
private String name;
private String wishMessage;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getWishMessage() {
return wishMessage;
}
public void setWishMessage(String wishMessage) {
this.wishMessage = wishMessage;
}
public String sayHello(){
return wishMessage+" "+name;
}
}
Welcome.java
package com.durgasoft.beans;
public class Welcome {
private String name;
private String wishMessage;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getWishMessage() {
return wishMessage;
}
public void setWishMessage(String wishMessage) {
this.wishMessage = wishMessage;
}
public String sayWelcome(){
return wishMessage+" "+name;
}
}
Main.java
import com.durgasoft.beans.Hello;
import com.durgasoft.beans.Welcome;
import com.durgasoft.beans.Wish;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("Spring-Config.xml");
Wish wish = (Wish) applicationContext.getBean("wish");
System.out.println(wish.sayWish());
Hello hello = (Hello) applicationContext.getBean("hello");
System.out.println(hello.sayHello());
Welcome welcome = (Welcome) applicationContext.getBean("welcome");
System.out.println(welcome.sayWelcome());
}
}
Spring-Config.xml
<?xml version="1.0" encoding="UTF-8"?>
<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 name="wish" class="com.durgasoft.beans.Wish">
<property name="name" value="Durga"/>
<property name="wishMessage" value="Good Morning"/>
</bean>
<bean name="hello" class="com.durgasoft.beans.Hello" parent="wish">
<property name="wishMessage" value="Hello"/>
</bean>
<bean name="welcome" class="com.durgasoft.beans.Welcome" parent="wish">
<property name="wishMessage" value="Welcome"/>
</bean>
</beans>
In the above bean configuration file, if we want to make a bean definition as an abstract bean definition then we can use “abstract” attribute in <bean> tag with the value “true”, where the abstract bean is not for creating object and not for accessing any business method, it is for the same of declaring reusable properties and their values.
In Spring applications, abstract bean definitions are also called template beans, for the Template beans no need to provide bean classes.
Spring-Config.xml
<?xml version="1.0" encoding="UTF-8"?>
<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 name="wish" abstract="true">
<property name="name" value="Durga"/>
<property name="wishMessage" value="Good Morning"/>
</bean>
<bean name="hello" class="com.durgasoft.beans.Hello" parent="wish">
<property name="wishMessage" value="Hello"/>
</bean>
<bean name="welcome" class="com.durgasoft.beans.Welcome" parent="wish">
<property name="wishMessage" value="Welcome"/>
</bean>
</beans>
Nested Beans
If we Declare a bean inside another bean then the internal bean is called a Nested Bean.
<beans>
—-----
<bean name=”--” class=”--”>
<property name=”--”>
<bean name=”--” class=”--”>
—-----
</bean>
</property>
</bean>
—-----
</beans>
EX:
Course.java
package com.durgasoft.beans;
public class Course {
private String courseId;
private String courseName;
private int courseCost;
public String getCourseId() {
return courseId;
}
public void setCourseId(String courseId) {
this.courseId = courseId;
}
public String getCourseName() {
return courseName;
}
public void setCourseName(String courseName) {
this.courseName = courseName;
}
public int getCourseCost() {
return courseCost;
}
public void setCourseCost(int courseCost) {
this.courseCost = courseCost;
}
}
Student.java
package com.durgasoft.beans;
public class Student {
private String studentId;
private String studentName;
private String studentAddress;
private Course studentCourse;
public String getStudentId() {
return studentId;
}
public void setStudentId(String studentId) {
this.studentId = studentId;
}
public String getStudentName() {
return studentName;
}
public void setStudentName(String studentName) {
this.studentName = studentName;
}
public String getStudentAddress() {
return studentAddress;
}
public void setStudentAddress(String studentAddress) {
this.studentAddress = studentAddress;
}
public void setStudentCourse(Course studentCourse) {
this.studentCourse = studentCourse;
}
public Course getStudentCourse() {
return studentCourse;
}
public void getStudentDetails(){
System.out.println("Student Details");
System.out.println("-----------------------");
System.out.println("Student Id : "+studentId);
System.out.println("Student Name : "+studentName);
System.out.println("Student Address : "+studentAddress);
System.out.println();
System.out.println("Course Details");
System.out.println("-------------------------");
System.out.println("Course Id : "+studentCourse.getCourseId());
System.out.println("Course Name : "+studentCourse.getCourseName());
System.out.println("Course Cost : "+studentCourse.getCourseCost());
}
}
Main.java
import com.durgasoft.beans.Student;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("Spring-Config.xml");
Student student = (Student) applicationContext.getBean("student");
student.getStudentDetails();
}
}
Spring-Config.xml
<?xml version="1.0" encoding="UTF-8"?>
<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 name="student" class="com.durgasoft.beans.Student">
<property name="studentId" value="S-111"/>
<property name="studentName" value="Durga"/>
<property name="studentAddress" value="Hyd"/>
<property name="studentCourse">
<bean name="course" class="com.durgasoft.beans.Course">
<property name="courseId" value="C-111"/>
<property name="courseName" value="JAVA"/>
<property name="courseCost" value="50000"/>
</bean>
</property>
</bean>
</beans>
BeanPostProcessor
The main purpose of the BeanPostProcessor is to customize the bean initialization process, that is, BeanPostprocessor has defined methods to execute before initialization of the Bean and after initialization of the Bean.
BeanPostProcessor is an interface provided by Spring Framework and it has provided the following methods to execute before bean initialization and after bean initialization.
public void postProcessBeforeInitialization(Object bean, String beanName)
It will be executed before the bean initialization.
public void postProcessAfterInitialization(Object bean, String beanName)
It will be executed after the bean initialization.
To utilize the BeanPostprocessor in spring applications we have to declare an user defined class , we have to implement the BeanPostprocessor interface and we have to configure the implementation class in the spring configuration file.
EX:
Hello.java
package com.durgasoft.beans;
public class Hello {
static{
System.out.println("Hello Bean Loading.....");
}
private String name;
public Hello(){
System.out.println("Hello Bean Instantiation......");
}
public void init(){
System.out.println("Hello Bean Initialization......");
}
public void setName(String name) {
this.name = name;
System.out.println("Hello Bean : setName() Method.....");
}
public String getName() {
return name;
}
public String sayHello(){
return "Hello "+name;
}
public void destroy(){
System.out.println("Hello Bean Deinstantiation......");
}
}
BeanPostprocessorImpl.java
package com.durgasoft.postprocessors;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.annotation.Bean;
public class BeanPostProcessorImpl implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("BeanPostprocessor: Before "+beanName+" Initialization");
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("BeanPostprocessor: After "+beanName+" Initialization");
return bean;
}
}
Main.java
import com.durgasoft.beans.Hello;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main {
public static void main(String[] args) {
AbstractApplicationContext applicationContext = new ClassPathXmlApplicationContext("Spring-Config.xml");
Hello hello = (Hello) applicationContext.getBean("hello");
System.out.println(hello.sayHello());
applicationContext.registerShutdownHook();
}
}
Spring-Config.xml
<?xml version="1.0" encoding="UTF-8"?>
<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"
default-init-method="init" default-destroy-method="destroy"
>
<bean name="hello" class="com.durgasoft.beans.Hello">
<property name="name" value="Durga"/>
</bean>
<bean name="beanPostProcessor" class="com.durgasoft.postprocessors.BeanPostProcessorImpl"/>
</beans>
In Spring application, if we declare more than one bean and if we provide only one BeanPostprocssor then the single BeanPostprocessor is applicable for all the bean components which are recognized by the IOC Container.
With the above nature, we can utilize the BeanPostprocessor to provide a common initialization process to all the beans which are provided in the Spring application.
In a Single Spring application, it is possible to provide more than one BeanPostProcessor, in this case Spring Framework will execute all the BeanPostProcessors in an order in which we have configured Bean Post processors in the Spring Configuration file.
EX:
Wish.java
package com.durgasoft.beans;
public class Hello {
static{
System.out.println("Hello Bean Loading....");
}
private String name;
public Hello(){
System.out.println("Hello Bean Instantiation.....");
}
public void init(){
System.out.println("Hello Bean Initialization....");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
System.out.println("Hello Bean : setName() method....");
}
public String sayHello(){
return "Hello "+name;
}
public void destroy(){
System.out.println("Hello Bean De-instantiation......");
}
}
Hello.java
package com.durgasoft.beans;
public class Hello {
static{
System.out.println("Hello Bean Loading....");
}
private String name;
public Hello(){
System.out.println("Hello Bean Instantiation.....");
}
public void init(){
System.out.println("Hello Bean Initialization....");
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
System.out.println("Hello Bean : setName() method....");
}
public String sayHello(){
return "Hello "+name;
}
public void destroy(){
System.out.println("Hello Bean De-instantiation......");
}
}
Welcome.java
package com.durgasoft.beans;
public class Welcome {
static{
System.out.println("Welcome Bean Loading....");
}
private String name;
public Welcome(){
System.out.println("Welcome Bean Instantiation.....");
}
public void init(){
System.out.println("Welcome Bean Initialization......");
}
public void setName(String name) {
this.name = name;
System.out.println("Welcome Bean : setName() Method.....");
}
public String getName() {
return name;
}
public String sayWelcome(){
return "Welcome "+name;
}
public void destroy(){
System.out.println("Welcome Bean De-instantiation......");
}
}
BeanPostProcessorImpl1.java
package com.durgasoft.postprocessors;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
public class BeanPostProcessorImpl1 implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("BeanPostProcessor-1 for "+beanName+" Bean Before Initialization");
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("BeanPostProcessor-1 for "+beanName+" Bean After Initialization");
return bean;
}
}
BeanPostProcessorImpl2.java
package com.durgasoft.postprocessors;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
public class BeanPostProcessorImpl2 implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("BeanPostProcessor-2 for "+beanName+" Bean Before Initialization");
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("BeanPostProcessor-2 for "+beanName+" Bean After Initialization");
return bean;
}
}
BeanPostProcessorImpl3.java
package com.durgasoft.postprocessors;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
public class BeanPostProcessorImpl3 implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("BeanPostProcessor-3 for "+beanName+" Bean Before Initialization");
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("BeanPostProcessor-3 for "+beanName+" Bean After Initialization");
return bean;
}
}
Spring-Config.xml
<?xml version="1.0" encoding="UTF-8"?>
<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"
default-init-method="init" default-destroy-method="destroy"
>
<bean name="wish" class="com.durgasoft.beans.Wish" >
<property name="name" value="Durga"/>
</bean>
<bean name="hello" class="com.durgasoft.beans.Hello" parent="wish" />
<bean name="welcome" class="com.durgasoft.beans.Welcome" parent="wish" />
<bean name="beanPostprocessor1" class="com.durgasoft.postprocessors.BeanPostProcessorImpl1"/>
<bean name="beanPostprocessor2" class="com.durgasoft.postprocessors.BeanPostProcessorImpl2"/>
<bean name="beanPostprocessor3" class="com.durgasoft.postprocessors.BeanPostProcessorImpl3"/>
</beans>
Main.java
import com.durgasoft.beans.Hello;
import com.durgasoft.beans.Welcome;
import com.durgasoft.beans.Wish;
import org.springframework.context.support.AbstractApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main {
public static void main(String[] args) {
AbstractApplicationContext abstractApplicationContext = new ClassPathXmlApplicationContext("Spring-Config.xml");
Wish wish = (Wish) abstractApplicationContext.getBean("wish");
System.out.println(wish.sayWish());
Hello hello = (Hello) abstractApplicationContext.getBean("hello");
System.out.println(hello.sayHello());
Welcome welcome = (Welcome) abstractApplicationContext.getBean("welcome");
System.out.println(welcome.sayWelcome());
abstractApplicationContext.registerShutdownHook();
}
}
Output :
Wish Bean Loading....
Wish Bean Instantiation.....
Wish Bean : setName() Method.....
BeanPostProcessor-1 for wish Bean Before Initialization
BeanPostProcessor-2 for wish Bean Before Initialization
BeanPostProcessor-3 for wish Bean Before Initialization
Wish Bean Initialization......
BeanPostProcessor-1 for wish Bean After Initialization
BeanPostProcessor-2 for wish Bean After Initialization
BeanPostProcessor-3 for wish Bean After Initialization
Hello Bean Loading....
Hello Bean Instantiation.....
Hello Bean : setName() method....
BeanPostProcessor-1 for hello Bean Before Initialization
BeanPostProcessor-2 for hello Bean Before Initialization
BeanPostProcessor-3 for hello Bean Before Initialization
Hello Bean Initialization....
BeanPostProcessor-1 for hello Bean After Initialization
BeanPostProcessor-2 for hello Bean After Initialization
BeanPostProcessor-3 for hello Bean After Initialization
Welcome Bean Loading....
Welcome Bean Instantiation.....
Welcome Bean : setName() Method.....
BeanPostProcessor-1 for welcome Bean Before Initialization
BeanPostProcessor-2 for welcome Bean Before Initialization
BeanPostProcessor-3 for welcome Bean Before Initialization
Welcome Bean Initialization......
BeanPostProcessor-1 for welcome Bean After Initialization
BeanPostProcessor-2 for welcome Bean After Initialization
BeanPostProcessor-3 for welcome Bean After Initialization
Good Morning Durga
Hello Durga
Welcome Durga
Welcome Bean De-instantiation......
Hello Bean De-instantiation......
Wish Bean De-instantiation......
In Spring applications, if we provide more than one BeanPostprocessor then the Spring Framework will execute all the BeanPostProcessors in their configuration order in the Spring Configuration File, here if we want to execute all the Bean Post processors in our own ordering then we have to use “Ordered” interface.
If we want to use Ordered interface in the Spring applications then we have to implement Ordered interface in the BeanPostProcessor implementation class and implement getOrder() method by returning a value which represents the order of the current BeanPostprocessor.
EX:
BeanPostProcessorImpl1.java
package com.durgasoft.postprocessors;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.core.Ordered;
public class BeanPostProcessorImpl1 implements BeanPostProcessor, Ordered {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("BeanPostProcessor-1 for "+beanName+" Bean Before Initialization");
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("BeanPostProcessor-1 for "+beanName+" Bean After Initialization");
return bean;
}
@Override
public int getOrder() {
return 3;
}
}
BeanPostProcessorImpl2.java
package com.durgasoft.postprocessors;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.core.Ordered;
public class BeanPostProcessorImpl2 implements BeanPostProcessor, Ordered {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("BeanPostProcessor-2 for "+beanName+" Bean Before Initialization");
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("BeanPostProcessor-2 for "+beanName+" Bean After Initialization");
return bean;
}
@Override
public int getOrder() {
return 2;
}
}
BeanPostprocessorImpl3.java
package com.durgasoft.postprocessors;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.core.Ordered;
public class BeanPostProcessorImpl3 implements BeanPostProcessor, Ordered {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("BeanPostProcessor-3 for "+beanName+" Bean Before Initialization");
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("BeanPostProcessor-3 for "+beanName+" Bean After Initialization");
return bean;
}
@Override
public int getOrder() {
return 1;
}
}
Spring-config.xml
<?xml version="1.0" encoding="UTF-8"?>
<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"
default-init-method="init" default-destroy-method="destroy"
>
<bean name="wish" class="com.durgasoft.beans.Wish" >
<property name="name" value="Durga"/>
</bean>
<bean name="hello" class="com.durgasoft.beans.Hello" parent="wish" />
<bean name="welcome" class="com.durgasoft.beans.Welcome" parent="wish" />
<bean name="beanPostprocessor1" class="com.durgasoft.postprocessors.BeanPostProcessorImpl1"/>
<bean name="beanPostprocessor2" class="com.durgasoft.postprocessors.BeanPostProcessorImpl2"/>
<bean name="beanPostprocessor3" class="com.durgasoft.postprocessors.BeanPostProcessorImpl3"/>
</beans>
Output :
Wish Bean Loading....
Wish Bean Instantiation.....
Wish Bean : setName() Method.....
BeanPostProcessor-3 for wish Bean Before Initialization
BeanPostProcessor-2 for wish Bean Before Initialization
BeanPostProcessor-1 for wish Bean Before Initialization
Wish Bean Initialization......
BeanPostProcessor-3 for wish Bean After Initialization
BeanPostProcessor-2 for wish Bean After Initialization
BeanPostProcessor-1 for wish Bean After Initialization
Hello Bean Loading....
Hello Bean Instantiation.....
Hello Bean : setName() method....
BeanPostProcessor-3 for hello Bean Before Initialization
BeanPostProcessor-2 for hello Bean Before Initialization
BeanPostProcessor-1 for hello Bean Before Initialization
Hello Bean Initialization....
BeanPostProcessor-3 for hello Bean After Initialization
BeanPostProcessor-2 for hello Bean After Initialization
BeanPostProcessor-1 for hello Bean After Initialization
Welcome Bean Loading....
Welcome Bean Instantiation.....
Welcome Bean : setName() Method.....
BeanPostProcessor-3 for welcome Bean Before Initialization
BeanPostProcessor-2 for welcome Bean Before Initialization
BeanPostProcessor-1 for welcome Bean Before Initialization
Welcome Bean Initialization......
BeanPostProcessor-3 for welcome Bean After Initialization
BeanPostProcessor-2 for welcome Bean After Initialization
BeanPostProcessor-1 for welcome Bean After Initialization
Good Morning Durga
Hello Durga
Welcome Durga
Welcome Bean De-instantiation......
Hello Bean De-instantiation......
Wish Bean De-instantiation......
BeanFactoryPostProcessor
The main purpose of the BeanFactoryPostprocessor is to modify the properties data which we provided in a bean definition in the Spring Configuration file.
If we want to use BeanFactoryPostprocessor in Spring applications then we have to use the following steps.
- Declare an user defined class.
- Implement
BeanFactoryPostProcessorinterface. - Provide Implementation to
postProcessBeanFactory()Method.- a. Get Bean Definition.
- b. Get
MutablePropertyValues. - c. Set new values to the
MutablePropertyValuesobject by usingaddProperty()method.
EX:
User.java
package com.durgasoft.beans;
public class User {
private String userName;
private String userAddress;
private String userEmailId;
private String userMobileNumber;
public String getUserAddress() {
return userAddress;
}
public void setUserAddress(String userAddress) {
this.userAddress = userAddress;
}
public String getUserEmailId() {
return userEmailId;
}
public void setUserEmailId(String userEmailId) {
this.userEmailId = userEmailId;
}
public String getUserMobileNumber() {
return userMobileNumber;
}
public void setUserMobileNumber(String userMobileNumber) {
this.userMobileNumber = userMobileNumber;
}
public String getUserName() {
return userName;
}
public void setUserName(String userName) {
this.userName = userName;
}
public void getUSerDetails(){
System.out.println("User Details");
System.out.println("---------------------");
System.out.println("User Name : "+userName);
System.out.println("User Address : "+userAddress);
System.out.println("User Email Id : "+userEmailId);
System.out.println("User Mobile Number : "+userMobileNumber);
}
}
BeanFactoryPostProcessorImpl.java
package com.durgasoft.postprocessor;
import org.springframework.beans.BeansException;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.PropertyValue;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
public class BeanFactoryPostProcessorImpl implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
BeanDefinition beanDefinition = beanFactory.getBeanDefinition("user");
MutablePropertyValues propertyValues = beanDefinition.getPropertyValues();
propertyValues.addPropertyValue("userName", "Durga N");
propertyValues.addPropertyValue("userAddress", "Durgasoft, 202, HMDA, Mitrivanam, Ameerpet, Hyd-38");
propertyValues.addPropertyValue("userEmailId", "durga@durgasoft.com");
propertyValues.addPropertyValue("userMobileNumber", "91-9988776655");
}
}
Spring-Config.xml
<?xml version="1.0" encoding="UTF-8"?>
<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 name="user" class="com.durgasoft.beans.User">
<property name="userName" value="Durga"/>
<property name="userAddress" value="Hyd"/>
<property name="userEmailId" value="durga"/>
<property name="userMobileNumber" value="9988776655"/>
</bean>
<bean name="beanFactoryPostProcessor" class="com.durgasoft.postprocessor.BeanFactoryPostProcessorImpl"/>
</beans>
Main.java
import com.durgasoft.beans.User;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class Main {
public static void main(String[] args) {
ApplicationContext applicationContext = new ClassPathXmlApplicationContext("Spring-Config.xml");
User user = (User) applicationContext.getBean("user");
user.getUSerDetails();
}
}
Output :
User Details
---------------------
User Name : Durga N
User Address : Durgasoft, 202, HMDA, Mitrivanam, Ameerpet, Hyd-38
User Email Id : durga@durgasoft.com
User Mobile Number : 91-9988776655