A Spring process follows bean based approach.The Spring bean is created, managed and dispensed by the Spring IoC container. Each Spring bean has a lifecycle and the lifecycle has to undergo the following stages:
- Instantiate – The Spring container instantiates the bean.
- Populate properties- Spring IoC container injects the bean’s properties.
- Set Bean Name- Spring container sets the bean name. If the bean implements BeanNameAware, spring container passes the bean’s id to setBeanName() method.
- Set Bean Factory-If the bean implements BeanFactoryAware, Spring container passes theBeanFactory to setBeanFactory().
- Pre Initialization-This stage is also called the bean postprocess . If there are anyBeanPostProcessors, theSpring container calls the postProcesserBeforeInitialization () method.
- Initialize beans- If the bean implements IntializingBean,its afterPropertySet()method is called. If the bean has init method declaration, the specified initialization method is called.
- Post Initialization- IfBeanPostProcessors is implemented by the bean, the Spring container calls their postProcessAfterinitalization() method.
- Ready to Use- Now the bean is ready to be used by the application.
- Destroy- The bean is destroyed during this stage. If the bean implements DisposableBean, the Spring IoC container will call the destroy() method . If a custom destroy () method is defined, the container calls the specified method.
Although there are many stages in the Spring bean lifecycle, in this post I will discuss two important bean lifecycle callback methods which are required at the time of bean initialization and its destruction and how we can customize them.
also read: follow us on @twitter and @facebook
- Spring Tutorials ( Collection for Spring reference documentations)
- Spring Framework Interview Questions
- Email Integration in Spring Framework
- Introduction to Spring REST Services
What is Spring Callback Methods?
Definition
Callback methods are those methods which are used by container during the lifecycle of an instance to manage it. Callback methods are invoked by container after instance is instantiated and before instance is destroyed.
Types
Spring has two callbacks- initialization and destruction.
1. Initialization
This interface org.springframework.beans.factory.InitializingBean interface allows a bean to perform initialization work. This interface has a method afterPropertiesSet() which is invoked by container after bean initialization(after all properties are set). So you can simply implement this interface and initialization work can be done inside afterPropertiesSet() method as follows:
afterPropertiesSet() method
public class ExampleBean implements InitializingBean { public void afterPropertiesSet() { // perform some initialization work here } }
When using the XML-based configuration metadata, you can use the init-method attribute to specify the name of the method that has a return void, no argument method signature. The snippet from our HelloWorld example (from Section Example):
<bean id="helloWorld" class="net.javabeat.HelloWorld" init-method="init"> ....... </bean>
The sample class definition would be (snippet from our HelloWorld example Section Example):
public class HelloWorld { public void init() { // do some initialization work } }
2. Destruction
The org.springframework.beans.factory.DisposableBean interface allows a bean to get a callback when the container containing it is destroyed. This interface has a method destroy() which is invoked by container before bean is destroyed.
So to enable a destroy callback, simply implement the above interface and finalization work can be done inside destroy() method as follows:
public class ExampleBean implements DisposableBean { public void destroy() { // do the work to be performed before bean destruction } }
When using the XML-based configuration metadata, you can use the destroy-method attribute to specify the name of the method that has a return void, no argument method signature. The following is small example.
<bean id="helloWorld" class="net.javabeat.HelloWorld" destroy-method="destroy"> <property name="message" value="Hello World!"/> </bean>
The class definition:
public class HelloWorld { public void destroy() { // do some destruction work } }
If you are using Spring’s IoC container in a non-web application environment; for example, in a rich client desktop environment; you register a shutdown hook with the JVM. Doing so ensures a graceful shutdown and calls the relevant destroy methods on your singleton beans so that all resources are released. Of course, you must still configure and implement these destroy callbacks correctly.
It is recommended to avoid using the InitializingBean or DisposableBean callbacks, because XML configuration gives much more flexibility in terms of naming the method.
Example Application
Let’s write an application to check the custom callback methods. To start off, a working Eclipse IDE should be in place. Once the IDE is ready, follow the steps to create a Spring application:
- Create a project with a name Spring-Custom-Callback and create a package net.javabeat under the src folder in the created project.
- Add required Spring libraries using Add External JARs option
- antlr-2.7.2.jar
- spring-aop-3.2.2.RELEASE.jar
- spring-aspects-3.2.2.RELEASE.jar
- spring-beans-3.2.2.RELEASE.jar
- spring-context-support-3.2.2.RELEASE.jar
- spring-context-3.2.2.RELEASE.jar
- spring-core-3.2.2.RELEASE.jar
- spring-expression-3.2.2.RELEASE.jar
- commons-logging-1.1.1.jar
- Create Java classes HelloWorld and MainApp under the net.javabeat package.
- Create Beans configuration file beans.xml under the src folder.
- The final step is to create the content of all the Java files and Bean Configuration file and run the application as explained below
The contents of the bean HelloWorld are as below:
package net.javabeat; public class HelloWorld { private String message; public HelloWorld() { System.out.println(" ***** HelloWorld Bean instantiated *****"); } public void setMessage(String message) { this.message = message; } public String getMessage() { System.out.println("The Greeting Message : " + message); return message; } public void init() { System.out.println("********** Initialization call back **********"); } public void destroy() { System.out.println("************ Destruction call back **************"); } }
The contents of MainApp.java file are as below:
package net.javabeat; import org.springframework.context.support.AbstractApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class MainApp { public static void main(String[] args) { AbstractApplicationContext context = new ClassPathXmlApplicationContext("Beans.xml"); HelloWorld obj = (HelloWorld) context.getBean("helloWorld"); obj.getMessage(); context.registerShutdownHook(); } }
Here it is required to register a shutdown hook- registerShutdownHook() method that is declared on the AbstractApplicationContext class. This will ensures a graceful shutdown and calls the relevant destroy methods.
Contents of the config file, Beans.xml are as below:
<?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-3.0.xsd"> <bean id="helloWorld" class="net.javabeat.HelloWorld" init-method="init" destroy-method="destroy"> <property name="message" value="Hello World!"/> </bean> </beans>
Final directory structure is as shown in the image below:
As a final step, let us run the application. If everything is fine with your application, the following output is printed:
***** HelloWorld Bean instantiated ***** ************ Initialization call back ************** The Greeting Message : Hello World! ************ Destruction call back **************
Default initialization and destroy methods
If there are too many beans having initialization and / or destroy methods with the same name, there is no need to declare init-method and destroy-method on every individual bean. Instead, the framework provides the facility to configure the init and destroy methods using default-init-method and default-destroy-method attributes on the element as follows:
<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-3.0.xsd" default-init-method="init" default-destroy-method="destroy"> <bean id="..." class="..."> <!-- configuration for bean goes here--> </bean> </beans>
Summary
In this article we saw what are callback methods in a spring life cycle. We also saw an example application, where we included init and destroy methods as our custom callback methods and saw how they get invoked. We also saw how to define default initialization and destroy methods. In the next post I shall explain about “Spring Container extension points”. If you are interested in receiving the future articles, please subscribe here