@Postconstruct and @Predestroy

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.

  1. 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.
  2. 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.
  3. 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
       }
   }
  1. 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:

  1. B) It marks a method to be called after a managed bean is constructed.
  2. C) After the managed bean is constructed.
  3. C) It is used to specify a method to be called before a managed bean is destroyed.
  4. D) To mark a method to be called before a managed bean is destroyed.
  5. B) Java Platform, Enterprise Edition (Java EE).
  6. A) void init()
  7. B) Before the managed bean is destroyed.
  8. C) Multiple @PostConstruct methods are allowed, but their order of execution is not guaranteed.
  9. D) @PreDestroy
  10. C) To manage resource cleanup and initialization in managed beans.

  1. Summary – @PostConstrcut and @PreDestroy is used for below purposes.
  2. @PostConstruct
  3. 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.
  4. No Return Value or Parameters: The method annotated with @PostConstruct must not have a return value (void) and should not take any parameters.
  5. 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.
  6. 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.
  7. 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.

  1. 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.
  2. 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.
  3. 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.