Spring provides various mechanisms for getting bean lifecycle callbacks. These callbacks are useful to take some specific action at a particular lifecycle stage. It's specially needed at the point when bean is fully initialized and all properties are set.
Following are the differents ways to receive callbacks after bean has initialized and before bean is destroyed:
- Using @PostConstruct and @PreDestroy
- Using 'initMethod' and 'destroyMethod' of @Bean annotation.
- By implementing InitializingBean and DisposableBean
This tutorial shows the example of @PostConstruct and @PreDestroy . The next two tutorials will show other methods of receiving callbacks.
Using @PostConstruct and @PreDestroy
The recommended way to receive initialization/destruction callbacks is by using @PostConstruct and @PreDestroy annotations
package com.logicbig.example;
public class OtherBean {
private String message;
public OtherBean(String message) {
this.message = message;
}
@Override
public String toString() {
return "OtherBean{" +
"message='" + message + '\'' +
'}';
}
}
package com.logicbig.example;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;
import org.springframework.beans.factory.annotation.Autowired;
public class MyBean {
private OtherBean otherBean;
public MyBean() {
System.out.println("MyBean constructor");
}
@PostConstruct
public void myPostConstruct() {
System.out.println(" @PostConstruct method");
}
@Autowired
public void setOtherBean(OtherBean otherBean) {
System.out.println("setOtherBean(): " + otherBean);
this.otherBean = otherBean;
}
public void doSomething() {
System.out.println("doSomething()");
}
@PreDestroy
public void cleanUp() {
System.out.println("@PreDestroy method");
}
}
In above example, we used setter injection, we can instead use field/constructor injection as well, the fields will be fully initialized the time when @PostConstruct method is called.
package com.logicbig.example;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class LifeCycleExample {
@Bean
public MyBean myBean() {
return new MyBean();
}
@Bean
public OtherBean otherBean() {
return new OtherBean("hello from otherBean!");
}
public static void main(String[] args) {
ConfigurableApplicationContext context =
new AnnotationConfigApplicationContext(LifeCycleExample.class);
context.registerShutdownHook();
System.out.println("-- accessing bean --");
MyBean bean = context.getBean(MyBean.class);
bean.doSomething();
System.out.println("-- finished --");
}
}
OutputMyBean constructor setOtherBean(): OtherBean{message='hello from otherBean!'} @PostConstruct method -- accessing bean -- doSomething() -- finished -- @PreDestroy method
Understanding registerShutdownHook() method
In above example, we used ConfigurableApplicationContext#registerShutdownHook(). This method registers a shutdown hook with the JVM runtime. This hook receives notification on JVM shutdown, at that time it closes the underlying context and calls all @PreDestroy and other standard register destroy methods. If we don't want to use this method then we have to call ConfigurableApplicationContext#close() ourselves at JVM shutdown, otherwise our destroy methods won't get called.
Example ProjectDependencies and Technologies Used: - spring-context 6.1.2 (Spring Context)
Version Compatibility: 3.2.3.RELEASE - 6.1.2 Version compatibilities of spring-context with this example: Versions in green have been tested.
- jakarta.jakartaee-api 10.0.0 (Eclipse Foundation)
- JDK 17
- Maven 3.8.1
|