Spring Bean Life Cycle Methods – InitializingBean, DisposableBean, @PostConstruct, @PreDestroy and *Aware interfaces
Spring Beans are the most important part of any Spring application. Spring ApplicationContext is responsible to initialize the Spring Beans defined in spring bean configuration file.
Spring Context is also responsible for injection dependencies in the bean, either through setter/constructor methods or by spring autowiring.
Sometimes we want to initialize resources in the bean classes, for example creating database connections or validating third party services at the time of initialization before any client request. Spring framework provide different ways through which we can provide post-initialization and pre-destroy methods in a spring bean.
- By implementing InitializingBean and DisposableBean interfaces – Both these interfaces declare a single method where we can initialize/close resources in the bean. For post-initialization, we can implement
InitializingBeaninterface and provide implementation ofafterPropertiesSet()method. For pre-destroy, we can implementDisposableBeaninterface and provide implementation ofdestroy()method. These methods are the callback methods and similar to servlet listener implementations.This approach is simple to use but it’s not recommended because it will create tight coupling with the Spring framework in our bean implementations.
- Providing init-method and destroy-method attribute values for the bean in the spring bean configuration file. This is the recommended approach because of no direct dependency to spring framework and we can create our own methods.
Note that both post-init and pre-destroy methods should have no arguments but they can throw Exceptions. We would also require to get the bean instance from the spring application context for these methods invocation.
@PostConstruct and @PreDestroy Annotations
Spring framework also support @PostConstruct and @PreDestroy annotations for defining post-init and pre-destroy methods. These annotations are part of javax.annotation package. However for these annotations to work, we need to configure our spring application to look for annotations. We can do this either by defining bean of type org.springframework.context.annotation.CommonAnnotationBeanPostProcessor or by context:annotation-config element in spring bean configuration file.
Let’s write a simple Spring application to showcase the use of above configurations. Create a Spring Maven project in Spring Tool Suite, final project will look like below image.

Spring Maven Dependencies
We don’t need to include any extra dependencies for configuring spring bean life cycle methods, our pom.xml file is like any other standard spring maven project.
<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework.samples</groupId>
<artifactId>SpringBeanLifeCycle</artifactId>
<version>0.0.1-SNAPSHOT</version> <properties> <!-- Generic properties -->
<java.version>1.7</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <!-- Spring -->
<spring-framework.version>4.0.2.RELEASE</spring-framework.version> <!-- Logging -->
<logback.version>1.0.13</logback.version>
<slf4j.version>1.7.5</slf4j.version> </properties> <dependencies>
<!-- Spring and Transactions -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring-framework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring-framework.version}</version>
</dependency> <!-- Logging with SLF4J & LogBack -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>${logback.version}</version>
<scope>runtime</scope>
</dependency> </dependencies>
</project>
pom.xml
Model Class
Let’s create a simple java bean class that will be used in service classes.
package com.journaldev.spring.bean;
public class Employee {
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Employee.java
InitializingBean and DisposableBean Example
Let’s create a service class where we will implement both the interfaces for post-init and pre-destroy methods.
package com.journaldev.spring.service; import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean; import com.journaldev.spring.bean.Employee; public class EmployeeService implements InitializingBean, DisposableBean{ private Employee employee; public Employee getEmployee() {
return employee;
} public void setEmployee(Employee employee) {
this.employee = employee;
} public EmployeeService(){
System.out.println("EmployeeService no-args constructor called");
} @Override
public void destroy() throws Exception {
System.out.println("EmployeeService Closing resources");
} @Override
public void afterPropertiesSet() throws Exception {
System.out.println("EmployeeService initializing to dummy value");
if(employee.getName() == null){
employee.setName("Pankaj");
}
}
}
EmployeeService.java
Service class with custom post-init and pre-destroy methods
Since we don’t want our services to have direct spring framework dependency, let’s create another form of Employee Service class where we will have post-init and pre-destroy methods and we will configure them in the spring bean configuration file.
package com.journaldev.spring.service;
import com.journaldev.spring.bean.Employee;
public class MyEmployeeService{
private Employee employee;
public Employee getEmployee() {
return employee;
}
public void setEmployee(Employee employee) {
this.employee = employee;
}
public MyEmployeeService(){
System.out.println("MyEmployeeService no-args constructor called");
}
//pre-destroy method
public void destroy() throws Exception {
System.out.println("MyEmployeeService Closing resources");
}
//post-init method
public void init() throws Exception {
System.out.println("MyEmployeeService initializing to dummy value");
if(employee.getName() == null){
employee.setName("Pankaj");
}
}
}
MyEmployeeService
We will look into the spring bean configuration file in a bit. Before that let’s create another service class that will use @PostConstruct and @PreDestroy annotations.
@PostConstruct and @PreDestroy Example
Below is a simple class that will be configured as spring bean and for post-init and pre-destroy methods, we are using @PostConstruct and @PreDestroy annotations.
package com.journaldev.spring.service; import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy; public class MyService { @PostConstruct
public void init(){
System.out.println("MyService init method called");
} public MyService(){
System.out.println("MyService no-args constructor called");
} @PreDestroy
public void destory(){
System.out.println("MyService destroy method called");
}
}
MyService.java
Spring Bean Configuration File
Let’s see how we will configure our beans in spring context file.
<?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"> <!-- Not initializing employee name variable-->
<bean name="employee" class="com.journaldev.spring.bean.Employee" /> <bean name="employeeService" class="com.journaldev.spring.service.EmployeeService">
<property name="employee" ref="employee"></property>
</bean> <bean name="myEmployeeService" class="com.journaldev.spring.service.MyEmployeeService"
init-method="init" destroy-method="destroy">
<property name="employee" ref="employee"></property>
</bean> <!-- initializing CommonAnnotationBeanPostProcessor is same as context:annotation-config -->
<bean class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor" />
<bean name="myService" class="com.journaldev.spring.service.MyService" />
</beans>
spring.xml
Notice that I am not initializing employee name in it’s bean definition. Since EmployeeService is using interfaces, we don’t need any special configuration here.
For MyEmployeeService bean, we are using init-method and destroy-method attributes to let spring framework know our custom methods to execute.
MyService bean configuration doesn’t have anything special, but as you can see that I am enabling annotation based configuration for this.
Our application is ready, let’s write a test program to see how different methods get executed.
Test Program
package com.journaldev.spring.main; import org.springframework.context.support.ClassPathXmlApplicationContext; import com.journaldev.spring.service.EmployeeService;
import com.journaldev.spring.service.MyEmployeeService; public class SpringMain { public static void main(String[] args) {
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("spring.xml"); System.out.println("Spring Context initialized"); //MyEmployeeService service = ctx.getBean("myEmployeeService", MyEmployeeService.class);
EmployeeService service = ctx.getBean("employeeService", EmployeeService.class); System.out.println("Bean retrieved from Spring Context"); System.out.println("Employee Name="+service.getEmployee().getName()); ctx.close();
System.out.println("Spring Context Closed");
} }
SpringMain.java
When we run above test program, we get below output.
Apr 01, 2014 10:50:50 PM org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@c1b9b03: startup date [Tue Apr 01 22:50:50 PDT 2014]; root of context hierarchy
Apr 01, 2014 10:50:50 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [spring.xml]
EmployeeService no-args constructor called
EmployeeService initializing to dummy value
MyEmployeeService no-args constructor called
MyEmployeeService initializing to dummy value
MyService no-args constructor called
MyService init method called
Spring Context initialized
Bean retrieved from Spring Context
Employee Name=Pankaj
Apr 01, 2014 10:50:50 PM org.springframework.context.support.ClassPathXmlApplicationContext doClose
INFO: Closing org.springframework.context.support.ClassPathXmlApplicationContext@c1b9b03: startup date [Tue Apr 01 22:50:50 PDT 2014]; root of context hierarchy
MyService destroy method called
MyEmployeeService Closing resources
EmployeeService Closing resources
Spring Context Closed
Important Points:
- From the console output it’s clear that Spring Context is first using no-args constructor to initialize the bean object and then calling the post-init method.
- The order of bean initialization is same as it’s defined in the spring bean configuration file.
- The context is returned only when all the spring beans are initialized properly with post-init method executions.
- Employee name is printed as “Pankaj” because it was initialized in the post-init method.
- When context is getting closed, beans are destroyed in the reverse order in which they were initialized i.e in LIFO (Last-In-First-Out) order.
You can uncomment the code to get bean of type MyEmployeeService and confirm that output will be similar and follow all the points mentioned above.
Spring Aware Interfaces
Sometimes we need Spring Framework objects in our beans to perform some operations, for example reading ServletConfig and ServletContext parameters or to know the bean definitions loaded by the ApplicationContext. That’s why spring framework provides a bunch of *Aware interfaces that we can implement in our bean classes.
org.springframework.beans.factory.Aware is the root marker interface for all these Aware interfaces. All of the *Aware interfaces are sub-interfaces of Aware and declare a single setter method to be implemented by the bean. Then spring context uses setter-based dependency injection to inject the corresponding objects in the bean and make it available for our use.
Spring Aware interfaces are similar to servlet listeners with callback methods and implementing observer design pattern.
Some of the important Aware interfaces are:
- ApplicationContextAware – to inject ApplicationContext object, example usage is to get the array of bean definition names.
- BeanFactoryAware – to inject BeanFactory object, example usage is to check scope of a bean.
- BeanNameAware – to know the bean name defined in the configuration file.
- ResourceLoaderAware – to inject ResourceLoader object, example usage is to get the input stream for a file in the classpath.
- ServletContextAware – to inject ServletContext object in MVC application, example usage is to read context parameters and attributes.
- ServletConfigAware – to inject ServletConfig object in MVC application, example usage is to get servlet config parameters.
Let’s see these Aware interfaces usage in action by implementing few of them in a class that we will configure as spring bean.
package com.journaldev.spring.service; import java.util.Arrays; import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.context.annotation.ImportAware;
import org.springframework.core.env.Environment;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.type.AnnotationMetadata; public class MyAwareService implements ApplicationContextAware,
ApplicationEventPublisherAware, BeanClassLoaderAware, BeanFactoryAware,
BeanNameAware, EnvironmentAware, ImportAware, ResourceLoaderAware { @Override
public void setApplicationContext(ApplicationContext ctx)
throws BeansException {
System.out.println("setApplicationContext called");
System.out.println("setApplicationContext:: Bean Definition Names="
+ Arrays.toString(ctx.getBeanDefinitionNames()));
} @Override
public void setBeanName(String beanName) {
System.out.println("setBeanName called");
System.out.println("setBeanName:: Bean Name defined in context="
+ beanName);
} @Override
public void setBeanClassLoader(ClassLoader classLoader) {
System.out.println("setBeanClassLoader called");
System.out.println("setBeanClassLoader:: ClassLoader Name="
+ classLoader.getClass().getName());
} @Override
public void setResourceLoader(ResourceLoader resourceLoader) {
System.out.println("setResourceLoader called");
Resource resource = resourceLoader.getResource("classpath:spring.xml");
System.out.println("setResourceLoader:: Resource File Name="
+ resource.getFilename());
} @Override
public void setImportMetadata(AnnotationMetadata annotationMetadata) {
System.out.println("setImportMetadata called");
} @Override
public void setEnvironment(Environment env) {
System.out.println("setEnvironment called");
} @Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
System.out.println("setBeanFactory called");
System.out.println("setBeanFactory:: employee bean singleton="
+ beanFactory.isSingleton("employee"));
} @Override
public void setApplicationEventPublisher(
ApplicationEventPublisher applicationEventPublisher) {
System.out.println("setApplicationEventPublisher called");
} }
MyAwareService.java
Spring Bean Configuration File
Very simple spring bean configuration file.
<?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.journaldev.spring.bean.Employee" /> <bean name="myAwareService" class="com.journaldev.spring.service.MyAwareService" /> </beans>
spring-aware.xml
Spring *Aware Test Program
package com.journaldev.spring.main;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.journaldev.spring.service.MyAwareService;
public class SpringAwareMain {
public static void main(String[] args) {
ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("spring-aware.xml");
ctx.getBean("myAwareService", MyAwareService.class);
ctx.close();
}
}
SpringAwareMain.java
Now when we execute above class, we get following output.
Apr 01, 2014 11:27:05 PM org.springframework.context.support.ClassPathXmlApplicationContext prepareRefresh
INFO: Refreshing org.springframework.context.support.ClassPathXmlApplicationContext@60a2f435: startup date [Tue Apr 01 23:27:05 PDT 2014]; root of context hierarchy
Apr 01, 2014 11:27:05 PM org.springframework.beans.factory.xml.XmlBeanDefinitionReader loadBeanDefinitions
INFO: Loading XML bean definitions from class path resource [spring-aware.xml]
setBeanName called
setBeanName:: Bean Name defined in context=myAwareService
setBeanClassLoader called
setBeanClassLoader:: ClassLoader Name=sun.misc.Launcher$AppClassLoader
setBeanFactory called
setBeanFactory:: employee bean singleton=true
setEnvironment called
setResourceLoader called
setResourceLoader:: Resource File Name=spring.xml
setApplicationEventPublisher called
setApplicationContext called
setApplicationContext:: Bean Definition Names=[employee, myAwareService]
Apr 01, 2014 11:27:05 PM org.springframework.context.support.ClassPathXmlApplicationContext doClose
INFO: Closing org.springframework.context.support.ClassPathXmlApplicationContext@60a2f435: startup date [Tue Apr 01 23:27:05 PDT 2014]; root of context hierarchy
Console output of the test program is simple to understand, I won’t go into much detail about that.
That’s all for the Spring Bean life cycle methods and injecting framework specific objects into the spring beans. Please download sample project from below link and analyze it to learn more about them.
原文地址:http://www.journaldev.com/2637/spring-bean-life-cycle-methods-initializingbean-disposablebean-postconstruct-predestroy-aware-interfaces
Spring Bean Life Cycle Methods – InitializingBean, DisposableBean, @PostConstruct, @PreDestroy and *Aware interfaces的更多相关文章
- 🙈羞,Spring Bean 初始化/销毁竟然有这么多姿势
文章来源:http://1t.click/bfHN 一.前言 日常开发过程有时需要在应用启动之后加载某些资源,或者在应用关闭之前释放资源.Spring 框架提供相关功能,围绕 Spring Bean ...
- Spring Bean的一生
Spring Bean的一生 When you work directly in Java, you can do anything you like with your objects and do ...
- Bean Life Cycle
Bean生命周期 Spring Bean Life Cycle https://www.tutorialspoint.com/spring/spring_bean_life_cycle.htm The ...
- Spring Bean 生命周期
转自:也谈Spring Bean的生命周期 开篇先用一张老图描述下Spring中Bean容器的生命周期. 插叙一下,记得某个博文中提到:“Spring的Bean容器只管理非单例Bean的生命周期,单例 ...
- Spring Bean InitializingBean和DisposableBean实例
在Spring中,InitializingBean和DisposableBean是两个标记接口,为Spring执行时bean的初始化和销毁某些行为时的有用方法. 对于Bean实现 Initializi ...
- Spring bean 实现InitializingBean和DisposableBean接口实现初始化和销毁前操作
# InitializingBean接口> Spring Bean 实现这个接口,重写afterPropertiesSet方法,这样spring初始化完这个实体类后会调用这个方法```@Over ...
- Spring InitializingBean init-method @PostConstruct 执行顺序
Spring 容器中的 Bean 是有生命周期的,Spring 允许在 Bean 在初始化完成后以及 Bean 销毁前执行特定的操作,常用的设定方式有以下三种: 通过实现 Initializing ...
- spring bean容器加载后执行初始化处理@PostConstruct
先说业务场景,我在系统启动后想要维护一个List常驻内存,因为我可能经常需要查询它,但它很少更新,而且数据量不大,明显符合缓存的特质,但我又不像引入第三方缓存.现在的问题是,该List的内容是从数据库 ...
- spring bean生命周期管理--转
Life Cycle Management of a Spring Bean 原文地址:http://javabeat.net/life-cycle-management-of-a-spring-be ...
随机推荐
- Codeforces 433 Div.2(A、B、C、D)
A. Fraction 暴力遍历1-1000,取组成的真分数比值最大且分子分母gcd为1时更新答案 代码: #include <stdio.h> #include <algorith ...
- yii2.0查询慢的原因
最近使用Yii2.0来搭建项目,测试的时候发现无论是请求列表数据还是发布数据,都很慢,然后我一步一步打印时间来查看哪里的问题,始终找不到原因,最后在网上看到这篇: 'db' => [ 'clas ...
- python下载链接内容
下面代码下载京东注册码,可接收参数num dir 可以将连接构造成其它网址,比如移动联通网上营业厅的验证码都是固定网址+13位时间戳的结构. #!/usr/bin/python #code utf-8 ...
- 寻宝游戏(bzoj 3991)
Description 小B最近正在玩一个寻宝游戏,这个游戏的地图中有N个村庄和N-1条道路,并且任何两个村庄之间有且仅有一条路径可达.游戏开始时,玩家可以任意选择一个村庄,瞬间转移到这个村庄,然后可 ...
- 洛谷P3144 [USACO16OPEN]关闭农场Closing the Farm
农夫约翰和他的奶牛准备去旅行,所以约翰想要把他的农场临时关闭. 农场有N个牛棚(牛棚从1到N编号),有M条路连接这些牛棚(1≤N,M≤3000). 约翰打算挨个关闭牛棚,在关牛棚的时候, 他突然想起一 ...
- STL~Deque简介
转自百度经验deque简介 deque是双向开口的连续性存储空间.虽说是连续性存储空间,但这种连续性只是表面上的,实际上它的内存是动态分配的,它在堆上分配了一块一块的动态储存区,每一块动态存储去本身是 ...
- 前端知识学习——html
<!-- Html,CSS,JS 三者的关系 ==> 人,衣服,动作. 以下展示 html 常用基本编码 --><!-- Html 在PyCharm中新建html文件默认给出的 ...
- 达梦数据库CAST与ROUND函数
https://blog.csdn.net/zry1266/article/details/50856260
- [BZOJ2815][ZJOI2012]灾难 灭绝树+拓扑排序+lca
灾难 [问题描述] 阿米巴是小强的好朋友. 阿米巴和小强在草原上捉蚂蚱.小强突然想,如果蚂蚱被他们捉灭绝了,那 么吃蚂蚱的小鸟就会饿死,而捕食小鸟的猛禽也会跟着灭绝,从而引发一系列的 生态灾难. 学过 ...
- AC日记——[国家集训队2011]旅游(宋方睿) cogs 1867
[国家集训队2011]旅游(宋方睿) 思路: 树链剖分,边权转点权: 线段树维护三个东西,sum,max,min: 当一个区间变成相反数时,sum=-sum,max=-min,min=-max: 来, ...