As long as Spring beans are required by the application, they exist within the container. For a bean to get into a usable state after instantiation, it needs to perform some initialization. Likewise, some clean up may be necessary when the bean is no longer required and is removed from the container.
Spring provides us with callback methods for the life cycle of the bean. You can have a method in your bean that runs when the bean has been created, and you can also have a method in your bean that is run when the bean is about to be destroyed.
Spring's BeanFactory
manages the life cycle of beans created through the Spring IoC container. The life cycle of beans consist of callback methods, which can be categorized broadly into the following two groups:
The following figure illustrates the two groups:
It represents a sequence of activities that take place between the bean instantiation and the handover of its reference to the client application:
Bean
class implements the BeanNameAware
interface, then call the setBeanName()
methodBean
class implements the BeanFactoryAware
interface, then call the setBeanFactory()
methodBean
class implements the ApplicationContextAware
interface, then call the setApplicationContext()
methodBeanPostProcessors
objects associated with the BeanFactory
interface that loaded the bean, then Spring will call the postProcessBeforeInitialization()
method before the properties for the bean are injectedBean
class implements the InitializingBean
interface, then call the afterPropertiesSet()
method once all the bean properties defined in the configuration file are injectedinit-method
attribute, then call this method after resolving the value for the attribute to a method name in the Bean
classpostProcessAfterInitialization()
method will be called if there are any bean post processors attached to the BeanFactory
interface that loads the beanThe bean has been initialized and the dependency has been injected. Now the bean is ready to be used by the application.
This represents the following sequence of activities:
Bean
class implements the DisposableBean
interface, then call the destroy()
method when the application no longer needs the bean referencedestroy-method
attribute, then call this method after resolving the value for the attribute to a method name in the Bean
class.There are two important bean life cycle callback methods that are required at the time of bean initialization and its destruction.
There are two ways in which you can achieve the initialization work after all necessary properties on the bean are set by the container:
org.springframework.beans.factory.InitializingBean
interfaceinit-method
in the XML configurationIn the EmployeeService.java
class, you'll find the following code:
package org.packt.Spring.chapter2.callbacks; public interface EmployeeService { public Long generateEmployeeID(); }
The org.springframework.beans.factory.InitializingBean
interface is used to specify a single method in a bean, as follows:
void afterPropertiesSet()throws Exception;
This method gets initialized whenever the bean containing this method is called.
In the EmployeeServiceImpl.java
class, you'll find the following code:
package org.packt.Spring.chapter2.callbacks; import org.springframework.beans.factory.InitializingBean; public class EmployeeServiceImpl implements EmployeeService, InitializingBean { @Override public Long generateEmployeeID() { return System.currentTimeMillis(); } @Override public void afterPropertiesSet() throws Exception { System.out.println("Employee afterPropertiesSet... "); } }
In the beans.xml
file, you'll find the following code:
... <bean id="employeeServiceBean" class="org.packt.Spring.chapter2.callbacks.EmployeeServiceImpl"> </bean> ...
Here, the InitializingBean
interface tells Spring that the EmployeeServiceImpl
bean needs to know when it's being initialized. A method of this bean needs to be called when the bean is initialized. The InitializingBean
interface has afterPropertiesSet()
, which needs to be implemented, and it will be called by Spring when this bean is initialized and all properties are set. This InitializingBean
interface is a marker for the bean to know that the afterPropertiesSet()
method of this bean needs to be called after initialization.
In the case of XML-based configuration metadata, you can use the init-method
attribute to specify the name of the method that has a void no-argument signature, which is to be called on the bean immediately upon instantiation.
In the beans.xml
file, you'll find the following code:
... <bean id="employeeServiceBean" class="org.packt.Spring.chapter2.callbacks.xml.EmployeeServiceImpl" init-method="myInit"> </bean> ...
In the EmployeeServiceImpl.java
class, you'll find the following code:
package org.packt.Spring.chapter2.callbacks.xml; public class EmployeeServiceImpl implements EmployeeService { @Override public Long generateEmployeeID() { return System.currentTimeMillis(); } public void myInit() { System.out.println("Employee myInit... "); } }
Now we have init-method
in the configuration beans.xml
file, which will take the method name as the value from the bean. So, instead of implementing an interface to this bean, we have a simple method that is called by Spring.
There are two ways you can do a destruction callback:
org.springframework.beans.factory.DisposableBean
interfacedestroy-method
in the XML configurationThe org.springframework.beans.factory.DisposableBean
interface is used to specify a single method in a bean, as follows:
void destroy() throws Exception;
This method allows a bean to get a callback whenever the Spring container containing this bean is destroyed.
In the EmployeeServiceImp.java
class, you'll find the following code:
package org.packt.Spring.chapter2.callbacks; import org.springframework.beans.factory.DisposableBean; public class EmployeeServiceImp implements EmployeeService, DisposableBean { @Override public Long generateEmployeeID() { return System.currentTimeMillis(); } @Override public void destroy() throws Exception { System.out.println("Employee destroy... "); } }
In the beans.xml
file, you'll find the following code:
... <bean id="employeeServiceBean" class="org.packt.Spring.chapter2.callbacks.EmployeeServiceImpl"> </bean> ...
The DisposableBean
interface has a destroy()
method. If a bean implements a DisposableBean
interface, then Spring will automatically call the destroy()
method of that bean before actually destroying the bean.
In the case of XML-based configuration metadata, you can use the destroy-method
attribute to specify the name of the method that has a void no-argument signature, which is called just before a bean is removed from the container.
In the beans.xml
file, you'll find the following code:
<bean id="employeeServiceBean" class="org.packt.Spring.chapter2.callbacks.xml.EmployeeServiceImpl" destroy-method="cleanUp"> </bean>
In the EmployeeServiceImpl.java
class, you'll find the following code:
package org.packt.Spring.chapter2.callbacks.xml; public class EmployeeServiceImpl implements EmployeeService { @Override public Long generateEmployeeID() { return System.currentTimeMillis(); } public void cleanUp() { System.out.println("Employee Cleanup... "); } }
Now we have destroy-method
in the configuration beans.xml
file, which will take the method name as a value from the bean. So, instead of implementing the interface to this bean, we have a simple method that is called by Spring.
In the PayrollSystem.java
class, you'll find the following code:
package org.packt.Spring.chapter2.callbacks.xml; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; public class PayrollSystem { public static void main(String[] args) { ConfigurableApplicationContext context = new ClassPathXmlApplicationContext("beans.xml"); EmployeeService employeeService = (EmployeeService) context.getBean("employeeServiceBean"); System.out.println(employeeService.generateEmployeeID()); context.close(); } }