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.
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.
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.
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.
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.
@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.
You can check out the complete project code from our GitHub Repository.
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
While we believe that this content benefits our community, we have not yet thoroughly reviewed it. If you have any suggestions for improvements, please let us know by clicking the “report an issue“ button at the bottom of the tutorial.
According to this stackoverflow answer https://stackoverflow.com/a/3406690/9642851 having `@PostConstruct` in constructor injection seems to be redundant.
- Ayman Patel
Hi . l want to learn that if we move some codes into the Configuration class "MyConfiguration " something like below ; @Configuration public class MyConfiguration { @Bean @Scope(value=“singleton”) public MyBean myBean() { return new MyBean(); } @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”); } } output will be cjanged . will be like below Verifying Resources MyBean instance create 1640296160 1640296160 Shutdown All Resources Closing All Resources why ? “Verifying Resources” output will come just after the “MyBean instance create” output . Ami right. please try then give me the answer
- Süleyman Yalman
Thanks for the tutorial. Please let me know why constructor is called only once during prototype execution. "MyBean instance created " is printed only once
- nagendra