Spring handles instantiating beans so it can also manage different events. The two key lifecycle events are initialization and destruction of beans.
These events give you a chance to have a method run for each lifecycle event. Other events control when the bean is instantiated.
As previously mentioned, an ApplicationContext eagerly instantiates beans, but beans can be excluded from eager instantiation in their configuration.
Also during the different lifecycle events Spring can set different resources, like the ApplicationContext, on a bean if it implements a certain interface.
Initialization and destruction are the two lifecycle events. This can be very useful managing different beans. A database connection pool could be configured to initialize the pool on startup and shutdown properly when the container is shutdown. Prototype beans only participate in the initialization lifecycle event. Once they are created, the container doesn't manage them any more and it's up to the developer to manage any destruction event that needs to occur on the bean.
The initialization lifecycle event occurs immediately after all the values being injected into the bean have been set.
There are a few different options to configure a bean for this lifecycle event. The InitializingBean interface can be used
and has a method signature of public void afterPropertiesSet() throws Exception. The bean's init-method attribute
can be set with any zero parameter method on the bean to be called for it's initialization event. The @PostConstruct annotation
can also be used to indicate a method should be called during initialization. The initialization lifecycle event happens immediately
after all beans and values have been injected into the main bean. AOP proxies haven't been applied at this point, so it's possible for
the initialization method to interact directly with a bean that will have a proxy when the startup process completes.
The destruction lifecycle event is called before the bean is destroyed. The destruction lifecycle event's interface
is DisposableBean and it's method signature is public void destroy() throws Exception.
The bean's destroy-method attribute can be set with any zero parameter method on the bean to be called for the destruction event.
The @PreDestroy annotation can also be used to indicate a method should be called during the destruction lifecycle event.
Based on the initialization order of beans, this same order will be followed in reverse for consistency.
If more than one method is defined for the initialization or destruction lifecycle events, each one will be executed. The order for each will be to run the annotated method, then the method of the interface, and finally the XML configured method. If the same method is defined more than once, it will still only be run once.
![]() | New Feature in Spring 2.5 |
|---|---|
When using Java 5 or higher, the |
Example 3.42. Lifecycle Event
The init() method has the @PostConstruct initialization annotation and the stop() method has the @PreDestroy annotation.
The afterPropertiesSet() method is the implementation of the InitializingBean interface and destroy() is the implementation of
the DisposableBean interface. The startup() method is defined in the XML configuration with the init-method attribute and
the shutdown() method is defined by the destroy-method attribute.
@PostConstruct
public void init() {
logger.debug("Initialization lifecycle event from @PostConstruct annotated method.");
}
public void afterPropertiesSet() throws Exception {
logger.debug("Initialization lifecycle event from InitializingBean method.");
}
public void startup() {
logger.debug("Initialization lifecycle event from Cusotm XML configured method.");
}
@PreDestroy
public void stop() {
logger.debug("Destruction lifecycle event from @PreDestroy annotated method.");
}
public void destroy() throws Exception {
logger.debug("Destruction lifecycle event from DisposableBean method.");
}
public void shutdown() {
logger.debug("Destruction lifecycle event from Cusotm XML configured method.");
}
Excerpt from chapter03-lifecycle-event/src/main/resources/applicationContext.xml
<!-- Register Annotation-based Post Processing Beans -->
<context:annotation-config />
<bean id="address"
class="org.springbyexample.springindepth.chapter03.lifecycleEvent.ProcessorContainer"
init-method="startup"
destroy-method="shutdown" />
When initializing an ApplicationContext directly, the method registerShutdownHook() must be called or destruction lifecycle events
for beans will not be processed when the JVM is shutdown. This method isn't actually available on the ApplicationContext interface,
but is available on AbstractApplicationContext which most ApplicationContext implementations extend.
Example 3.43. Register Shutdown Hook
When ProcessorRunner is run, destruction lifecycle events are processed. To see this fail
the BadProcessorRunner (which isn't shown) can be run and then destruction events aren't processed.
public static void main(String[] args) {
AbstractApplicationContext applicationContext = new ClassPathXmlApplicationContext("/applicationContext.xml");
applicationContext.registerShutdownHook();
}
Typically a bean's dependencies will be handled automatically since any bean set on a property will be instantiated before it can be set. If there is a case where there isn't a direct dependency, but another bean should still be instantiated first the bean's depends-on attribute can be used. The depends-on attribute can be a single bean or list of beans. Each bean in the list can be separated by a comma, semi-colon, or whitespace. The order beans are instantiated for creation is also followed when beans are destroyed. So if bean A depends on bean B, bean B will be destroyed before bean A.
An ApplicationContext will eagerly instantiate singleton beans on startup. If this is undesired behavior,
the bean's lazy-init attribute can be set to 'true' then the bean won't be instantiated until it is needed.
If another bean that is eagerly instantiated references this bean, it will instantiate the lazy bean at startup anyway.
So this is only useful if a lazy bean isn't referenced or only referenced by other lazy beans or non-singleton scope beans.
To change the default lazy initialization value for all beans, the root beans element default-lazy-init attribute can be set to 'true'.
Spring has a few interfaces that will have the container set different resources on the bean as it's initialized. The resource indicated by
the aware interface will be set after all the properties have been set, but before the initialization lifecycle event.
A few of the more commonly used interfaces will be covered here. BeanNameAware has the container set the bean's name which could be used for debugging.
BeanFactoryAware and ApplicationContextAware will give a bean access to the container's BeanFactory
and ApplicationContext respectively. They could be used to look up beans where standard injection and autowiring may not be sufficient,
but it's better to try to inject beans through the configuration than to look them up directly if at all possible.
MessageSourceAware will give a bean access to the defined MessageSource which can be used to resolve internationalized messages,
and the ResourceLoaderAware gives a bean access to the ResourceLoader which can be used to look up different resources from
the classpath, files, and URLs. The full list of aware interfaces is below.
ApplicationContextAwareApplicationEventPublisherAwareBeanClassLoaderAwareBeanFactoryAwareBeanNameAwareBeanNameAwareBootstrapContextAwareLoadTimeWeaverAwareMessageSourceAwareNotificationPublisherAwarePortletConfigAwarePortletContextAwareResourceLoaderAwareSchedulerContextAwareServletConfigAwareServletContextAwareTargetClassAware