In this post, we are going to learn about @PostConstruct and @PreDestroy annotations.
Understanding @PostConstruct annotation
The @PostConstruct
method is invoked by the Spring container just after the spring bean has been initialized. This means that it’s called immediately after the bean’s constructor has executed and all dependencies have been injected, but before any other method in the bean is invoked.
The purpose of @PostConstruct
is to allow us to perform any initialization or setup tasks. For example, database connection initialization, resource configuration, or logging setup.
Here’s an example to illustrate the usage of @PostConstruct
:
import javax.annotation.PostConstruct;
import org.springframework.stereotype.Service;
@Service
public class MyService {
@PostConstruct
public void init() {
// Initialization logic goes here
// This method is invoked after bean construction and dependency injection
}
// Other methods and fields of the bean
}
In this example, the init()
method with the @PostConstruct
annotation will be executed immediately after the MyService
bean has been constructed and dependencies (if any) have been injected.
Let’s see real-time use cases where we can use @PostConstruct annotation
The @PostConstruct
annotation is commonly used to perform initialization tasks that need to happen after a bean has been constructed but before it is used. Here are five real-time use cases where the @PostConstruct
method is used:
- Database Connection Initialization:
In a Java EE application that relies on a database, you can use@PostConstruct
to open a database connection pool or initialize database-related resources when a managed bean is instantiated. This ensures that the database resources are ready for use by other methods in the bean.
import javax.annotation.PostConstruct;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
@Service
public class DatabaseService {
private final DataSource dataSource;
@Autowired
public DatabaseService(DataSource dataSource) {
this.dataSource = dataSource;
}
@PostConstruct
public void initializeDatabaseConnectionPool() throws SQLException {
// Initialize the database connection pool
Connection connection = dataSource.getConnection();
// Perform any necessary database setup here
// The connection pool is now ready for use
}
}
- Resource Configuration:
If your application uses external resources like configuration files, properties, or environment variables, you can use@PostConstruct
to read and set up these resources during bean initialization. This allows your bean to be configured properly before it starts processing requests.
import javax.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
@Service
public class ResourceConfigurationService {
@Value("${app.config.property}")
private String configProperty;
@PostConstruct
public void configureResources() {
// Use the configProperty value to configure resources
// This method will be executed after bean instantiation
}
}
- Logging and Monitoring:
In applications that require logging or monitoring, you can use@PostConstruct
to initialize logging or monitoring tools. For example, you can set up a logging framework like Log4j or configure a monitoring agent to start collecting metrics as soon as the bean is created.
import javax.annotation.PostConstruct;
import org.springframework.stereotype.Service;
@Service
public class LoggingService {
@PostConstruct
public void initializeLogging() {
// Initialize a logging framework or agent
// Start collecting logs and metrics
}
}
- Security Setup:
Security-related tasks, such as authentication or authorization, can be configured in a@PostConstruct
method. For example, you might set up security roles, permissions, or authentication providers based on the bean’s role in the application.
import javax.annotation.PostConstruct;
import org.springframework.security.core.userdetails.UserDetailsManager;
import org.springframework.stereotype.Service;
@Service
public class SecuritySetupService {
private final UserDetailsManager userDetailsManager;
public SecuritySetupService(UserDetailsManager userDetailsManager) {
this.userDetailsManager = userDetailsManager;
}
@PostConstruct
public void configureSecurity() {
// Configure security roles, permissions, and authentication providers
// This method is executed after bean instantiation
}
}
- Caching and Preloading:
If your application uses caching to improve performance, you can use@PostConstruct
to preload cache data or configure the caching mechanism. This ensures that the cache is populated with data when the bean is initialized, reducing response times for subsequent requests.
import javax.annotation.PostConstruct;
import org.springframework.cache.CacheManager;
import org.springframework.stereotype.Service;
@Service
public class CachingService {
private final CacheManager cacheManager;
public CachingService(CacheManager cacheManager) {
this.cacheManager = cacheManager;
}
@PostConstruct
public void preloadCacheData() {
// Preload cache data or configure caching mechanisms
// This ensures that the cache is populated when the bean is initialized
}
}
Understanding @PreDestroy annotation
The @PreDestroy
annotation is used with a method indicating that this method should be called by the container before the bean is destroyed, allowing the bean to perform cleanup tasks or release resources.
Here are some key points about the @PreDestroy
annotation.
- Invocation Timing: The
@PreDestroy
annotated method is invoked by the container during the bean’s lifecycle when it’s about to be destroyed or removed from the container. This typically happens when the container is shutting down or when the bean’s scope ends, depending on the specific context in which the bean is managed. - Purpose: The primary purpose of
@PreDestroy
is to give the bean an opportunity to release any resources it has acquired during its lifecycle. This could include closing database connections, releasing file handles, stopping background tasks, or performing any other necessary cleanup operations. - Method Signature: The method marked with
@PreDestroy
must follow a specific signature. It should be a void method with no parameters. Here’s an example:
import javax.annotation.PreDestroy;
public class MyBean {
// ... other methods and fields ...
@PreDestroy
public void cleanup() {
// Perform cleanup tasks here
}
}
- Multiple
@PreDestroy
Methods: A managed bean can have multiple methods annotated with@PreDestroy
, but it’s important to note that the order of execution for these methods is not guaranteed. If you need a specific order of cleanup operations, you should manage that explicitly within your bean.
Here’s an example of how @PreDestroy
might be used in a Java EE or Spring application:
import javax.annotation.PreDestroy;
public class MyService {
// ... other methods and fields ...
@PreDestroy
public void cleanUp() {
// Release resources and perform cleanup tasks
}
}
In this example, the cleanUp
method will be called by the container or framework before the MyService
bean is destroyed, allowing it to perform any necessary cleanup operations.
Example of @PostConstruct and @PreDestroy
In this example, we have two classes one SpringMain.java and another one Config.java.
Config.java
import org.springframework.context.annotation.Configuration;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
@Configuration
public class Config {
@PostConstruct
public void init() {
System.out.println("init method is invoked() using postconstruct annotation");
}
@PreDestroy
public void cleanup() {
System.out.println("cleanup method is invoked() using PreDestroy annotation");
}
}
SpringMain.java
package com.javatute.main;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
@ComponentScan(basePackages = "com.javatute.*")
@SpringBootApplication
public class SpringMain {
public static void main(String[] args) {
SpringApplication.run(SpringMain.class, args);
}
}
When we run SpringMain.java class, at the console we can see init method is invoked() using postconstruct annotation in output. Once we try to shutdown server we can see cleanup method is invoked() using PreDestroy annotation as output in console.
Ten objective questions related to @Postconstruct and @Predestroy.
Question 1: What is the purpose of the @PostConstruct
annotation in Java?
A) It marks a method to be called before a managed bean is destroyed.
B) It marks a method to be called after a managed bean is constructed.
C) It is used to define a constructor for a Java class.
D) It is used to specify a method as a setter method.
Question 2: When is a method annotated with @PostConstruct
typically invoked?
A) After the managed bean is destroyed.
B) Before the managed bean is constructed.
C) After the managed bean is constructed.
D) During the initialization of the application context.
Question 3: Which of the following is true regarding the @PreDestroy
annotation?
A) It is used to create a new object instance.
B) It is used to mark a method as a constructor.
C) It is used to specify a method to be called before a managed bean is destroyed.
D) It is used to define a method that runs before a managed bean is constructed.
Question 4: What is the primary purpose of the @PreDestroy
annotation?
A) To mark a method to be called after a managed bean is constructed.
B) To define a method that runs during the initialization of the application context.
C) To specify a method as a setter method.
D) To mark a method to be called before a managed bean is destroyed.
Question 5: In which Java environment is the @PostConstruct
annotation commonly used?
A) Java Standard Edition (Java SE)
B) Java Platform, Enterprise Edition (Java EE)
C) Java Micro Edition (Java ME)
D) JavaFX applications
Question 6: which one is the most appropriate method signature for a method annotated with @PostConstruct
?
A) void init()
B) void postInit()
C) void setup()
D) void configure()
Question 7: In a Java EE application, when does the container typically invoke methods marked with @PreDestroy
?
A) Before the managed bean is constructed.
B) Before the managed bean is destroyed.
C) After the managed bean is constructed.
D) During the initialization of the application context.
Question 8: How many @PostConstruct
methods can a managed bean have?
A) Only one @PostConstruct
method is allowed per bean.
B) Multiple @PostConstruct
methods are allowed, and their order of execution is guaranteed.
C) Multiple @PostConstruct
methods are allowed, but their order of execution is not guaranteed.
D) There is no limit to the number of @PostConstruct
methods a bean can have.
Question 9: Which annotation is used to specify a method to be called before a managed bean is destroyed?
A) @PreConstruct
B) @BeforeDestroy
C) @PostConstruct
D) @PreDestroy
Question 10: What is the primary use case for @PostConstruct
and @PreDestroy
annotations?
A) To create new instances of managed beans.
B) To define constructors for Java classes.
C) To manage resource cleanup and initialization in managed beans.
D) To specify setter methods for managed beans.
Answers:
- B) It marks a method to be called after a managed bean is constructed.
- C) After the managed bean is constructed.
- C) It is used to specify a method to be called before a managed bean is destroyed.
- D) To mark a method to be called before a managed bean is destroyed.
- B) Java Platform, Enterprise Edition (Java EE).
- A) void init()
- B) Before the managed bean is destroyed.
- C) Multiple
@PostConstruct
methods are allowed, but their order of execution is not guaranteed. - D) @PreDestroy
- C) To manage resource cleanup and initialization in managed beans.
- Summary – @PostConstrcut and @PreDestroy is used for below purposes.
- @PostConstruct
- Initialization Callback:
@PostConstruct
is an annotation used in Java EE, Jakarta EE, and Spring to specify a method that should be called immediately after a bean is constructed by the container but before any other business logic methods are invoked on the bean. It is typically used for initialization tasks. - No Return Value or Parameters: The method annotated with
@PostConstruct
must not have a return value (void) and should not take any parameters. - Guaranteed Execution: The
@PostConstruct
annotated method is guaranteed to be executed exactly once during the lifecycle of the bean, immediately after the bean’s construction and dependency injection. This ensures that initialization tasks are performed consistently. - Use Cases: Common use cases for
@PostConstruct
include database connection initialization, resource configuration, logging and monitoring setup, security configuration, and caching and preloading data. It is a convenient way to centralize and encapsulate initialization logic for managed beans in your application. - Overall,
@PostConstruct
is a valuable tool for managing the lifecycle of beans and ensuring that they are properly initialized before they start executing their main business logic. It helps improve the robustness and reliability of Java EE, Jakarta EE, and Spring applications.
@PreDestroy- This is use for below purposes.
- Cleanup and Resource Release:
@PreDestroy
is used to mark a method within a managed bean that should be called by the container before the bean is destroyed. This provides an opportunity for the bean to perform cleanup operations, release resources, and gracefully shut down. - Lifecycle Management: It plays a crucial role in managing the lifecycle of Java EE or Spring beans. When a bean is no longer needed or when the application context is shutting down, the method annotated with
@PreDestroy
is executed to ensure that any acquired resources are properly released. - Method Signature: The method annotated with
@PreDestroy
must be a void method with no parameters. It follows a specific naming convention, and its purpose is to perform cleanup tasks that are essential for the correct operation of the bean and the application as a whole.
Note – we need to add below dependency to use @PostConstruct and @PreDestroy, since Java EE is depricated in Java 9.
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
<version>1.3.2</version>
</dependency>
That’s all about @Postconstruct and @Predestroy annotations.
See docs here.
- @Component not working in Spring Boot
- How to use @Where annotation in Hibernate
- @RestController and @Controller annotation example in Spring Boot.
- @RequestBody and @ResponseBody annotation example in Spring Boot.
- @PathVariable and @RequestParam annotations in Spring Boot.
- @RequestHeader annotation example by using Spring Boot.