In Spring lifecycle callbacks are manages by BeanPostProcessor implementations and several methods for extension are provided:
Bean Lifecycle Extensions
JSR-250 Annotations
Not a part of Spring core, must be included as a separate jar. Annotations @PostConstruct and @PreDestroy can be used to set lifecycle callbacks.
public class BeanLifecycleAnnotations extends BaseBean {
@PostConstruct
private void init() {
System.out.println("BeanLifecycle: PostConstruct");
}
@PreDestroy
private void destroy() {
System.out.println("BeanLifecycle: PreDestroy");
}
}
Init and Destroy methods
Spring specific configuration that can be used with XML and @Bean.
@Bean(initMethod = "init", destroyMethod = "destroy")
public BeanLifeCycleMethods beanLifeCycleMethods() {
}
Initialization callbacks
These are not recommended because they couple code to Spring implementation.
InitializingBean interface performs initialization work after the container has set all the necessary properties on the bean.
public class AnotherExampleBean implements InitializingBean {
@Override
public void afterPropertiesSet() {
// do some initialization work
}
}
DisposableBean interface allows a callback to the bean when the bean container is destroyed.
public class ExampleBean {
public void cleanup() {
// do some destruction work (like releasing pooled connections)
}
}
Multiple lifecycle mechanisms configured for the same bean, with different initialization methods, are called as follows:
- Methods annotated with
@PostConstruct
afterPropertiesSet()
as defined by theInitializingBean
callback interface- A custom configured
init()
method
Destroy methods are called in the same order:
- Methods annotated with
@PreDestroy
destroy()
as defined by theDisposableBean
callback interface- A custom configured
destroy()
method
Note: destroy callbacks are not invoked by prototype scope beans because there are not tracked by Application Context, their destruction and resource release bust be done manually.
BeanPostProcessor
The BeanPostProcessor interface can be itself customized logic to default steps, when Spring container finishes instantiating, configuring, and initializing a bean, several implementations of BeanPostProcessor can be called.
public class InstantiationTracingBeanPostProcessor implements BeanPostProcessor {
// simply return the instantiated bean as-is
public Object postProcessBeforeInitialization(Object bean, String beanName) {
return bean; // we could potentially return any object reference here...
}
public Object postProcessAfterInitialization(Object bean, String beanName) {
System.out.println("Bean '" + beanName + "' created : " + bean.toString());
return bean;
}
}
DestructionAwareBeanPostProcessor
Subinterface of BeanPostProcessor that adds a before-destruction callback.
public class DestructionAwareBeanPostProcessorExtension implements DestructionAwareBeanPostProcessor {
@Override
public void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException {
}
@Override
public boolean requiresDestruction(Object bean) {
return DestructionAwareBeanPostProcessor.super.requiresDestruction(bean);
}
}
Startup and Shutdown callbacks
The Lifecycle interface defines methods for objects that require their own lifecycle requirements and these will be called when the ApplicationContext itself receives start and stop signals.
public interface Lifecycle {
void start();
void stop();
boolean isRunning();
}
Aware Interfaces
ApplicationContextAware
Provides a reference to ApplicationContext in to the bean;
@Component
public class BeanPostProcessorExtension implements ApplicationContextAware {
private ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
}
BeanNameAware
Provides a reference to the name of the bean derived from it’s bean definition.
public class BeanContextAware extends BaseBean implements BeanNameAware{
public String name;
@Override
public void setBeanName(String name) {
this.name = name;
}
}
References
https://docs.spring.io/spring-framework/reference/core/beans/factory-nature.html
https://stackoverflow.com/questions/50681027/do-spring-prototype-beans-need-to-be-destroyed-manually