Spring PostConstruct and PreDestroy
When we configure Spring Beans using dependency injection, sometimes we want to make sure everything is initialized properly before our bean starts serving the client requests. Similarly, when the context is destroyed, we may have to close some resources used by spring bean.
Spring @PostConstruct
When we annotate a method in Spring Bean with @PostConstruct annotation, it gets executed after the spring bean is initialized. We can have only one method annotated with @PostConstruct annotation. This annotation is part of Common Annotations API and it’s part of JDK module javax.annotation-api. So if you are using this annotation in Java 9 or above, you will have to explicitly add this jar to your project. If you are using maven, then below dependency should be added to it.
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<version>1.3.2</version>
</dependency>
If you are on Java 8 or lower version, then you won’t have to add above dependency.
Spring @PreDestroy
When we annotate a Spring Bean method with PreDestroy annotation, it gets called when bean instance is getting removed from the context. This is a very important point to understand – if your spring bean scope is “prototype” then it’s not completely managed by the spring container and PreDestroy method won’t get called. If there is a method named shutdown or close then spring container will try to automatically configure them as callback methods when bean is being destroyed.
Spring @PostConstruct and @PreDestroy Example
Here is a simple spring bean with @PostConstruct and @PreDestroy methods.
package com.journaldev.spring;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
public class MyBean {
public MyBean() {
System.out.println("MyBean instance created");
}
@PostConstruct
private void init() {
System.out.println("Verifying Resources");
}
@PreDestroy
private void shutdown() {
System.out.println("Shutdown All Resources");
}
public void close() {
System.out.println("Closing All Resources");
}
}
Notice that I have also defined a close method to check whether it gets called when our bean is destroyed or not. Here is my simple spring configuration class.
package com.journaldev.spring;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
@Configuration
public class MyConfiguration {
@Bean
@Scope(value="singleton")
public MyBean myBean() {
return new MyBean();
}
}
I don’t need to explicitly specify my bean as a singleton but I will later change its value to “prototype” and see what happens with @PostConstruct and @PreDestroy methods. Here is my main class where I am creating spring context and getting few instances of MyBean.
package com.journaldev.spring;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class MySpringApp {
public static void main(String[] args) {
AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext();
ctx.register(MyConfiguration.class);
ctx.refresh();
MyBean mb1 = ctx.getBean(MyBean.class);
System.out.println(mb1.hashCode());
MyBean mb2 = ctx.getBean(MyBean.class);
System.out.println(mb2.hashCode());
ctx.close();
}
}
When we run above class, we get following output.
MyBean instance created
Verifying Resources
1640296160
1640296160
Shutdown All Resources
Closing All Resources
So @PostConstruct method is called after the bean is instantiated. When the context is getting closed, it’s calling both shutdown and close method.
Spring @PostConstruct and @PreDestroy with Prototype Scope
Just change the scope value to prototype in MyConfiguration and run the main class. You will get output like below.
MyBean instance created
Verifying Resources
1640296160
MyBean instance created
Verifying Resources
1863374262
So it’s clear that spring container is initializing the bean on every request, calling its @PostConstruct method and then handing it over to the client. Spring is not managing the bean after that and in this case, the client has to perform all the resource cleanup by directly calling the PreDestroy method.
Summary
@PostConstruct and @PreDestroy and important annotations to use with the spring bean lifecycle management. We can use them to verify that bean is properly initialized and then close all the resources when the bean is removed from the spring context.