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:

  1. Methods annotated with @PostConstruct
  2. afterPropertiesSet() as defined by the InitializingBean callback interface
  3. A custom configured init() method

Destroy methods are called in the same order:

  1. Methods annotated with @PreDestroy
  2. destroy() as defined by the DisposableBean callback interface
  3. 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