🎓 Top 15 Udemy Courses (80-90% Discount): My Udemy Courses - Ramesh Fadatare — All my Udemy courses are real-time and project oriented courses.
▶️ Subscribe to My YouTube Channel (178K+ subscribers): Java Guides on YouTube
▶️ For AI, ChatGPT, Web, Tech, and Generative AI, subscribe to another channel: Ramesh Fadatare on YouTube
@PostConstruct and @PreDestroy annotations in a Spring Boot application. These annotations are part of the Java EE specification and are used to define lifecycle callback methods for a bean.Table of Contents
- Introduction
- Key Concepts
- Using @PostConstruct and @PreDestroy in Spring
- Example Project Setup
- Real-World Use Case: Database Initialization
- Example Implementation
- Running the Application
- Conclusion
Introduction
The @PostConstruct annotation is used on a method that needs to be executed after dependency injection is done to perform any initialization. Similarly, the @PreDestroy annotation is used on methods that need to be executed before the bean is destroyed. These annotations are particularly useful for resource management and cleanup tasks.
Key Concepts
- @PostConstruct: Annotates a method that should be executed after the bean's dependencies have been injected.
- @PreDestroy: Annotates a method that should be executed just before the bean is removed from the context or destroyed.
Using @PostConstruct and @PreDestroy in Spring
@PostConstruct
This annotation is used on a method that needs to be run after the bean has been initialized and all dependencies have been injected. It is typically used for performing any setup or initialization tasks that need to be done after the bean's properties have been set.
@PreDestroy
This annotation is used on a method that needs to be run before the bean is destroyed. It is typically used for cleanup tasks such as releasing resources or closing connections.
Example Project Setup
Let's create a simple Maven project to demonstrate the usage of @PostConstruct and @PreDestroy annotations in a Spring application.
1. Create a Simple Maven Project
Create a simple Maven project using your favourite IDE. Below is the project structure for your reference:
src
├── main
│ ├── java
│ │ └── net
│ │ └── javaguides
│ │ └── spring
│ │ ├── AppConfig.java
│ │ ├── Application.java
│ │ ├── MessageService.java
│ │ ├── MessageServiceImpl.java
│ │ └── DatabaseService.java
│ └── resources
│ └── application.properties
2. The pom.xml File
Make sure to use Java 17 or later for Spring Framework 6:
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>net.javaguides</groupId>
<artifactId>spring-postconstruct-predestroy</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
</dependencies>
</project>
Real-World Use Case: Database Initialization
In a real-world application, you might need to initialize a database at startup and clean up resources when the application shuts down. The @PostConstruct and @PreDestroy annotations are perfect for such tasks.
Example Implementation
3. Create the MessageService Interface
MessageService.java
package net.javaguides.spring;
public interface MessageService {
String getMessage();
}
4. Create the MessageServiceImpl Class
MessageServiceImpl.java
package net.javaguides.spring;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;
import org.springframework.stereotype.Component;
@Component
public class MessageServiceImpl implements MessageService {
private String message;
@PostConstruct
public void init() {
message = "Hello, Spring!";
System.out.println("PostConstruct: MessageService initialized with message: " + message);
}
@Override
public String getMessage() {
return message;
}
@PreDestroy
public void cleanup() {
System.out.println("PreDestroy: Cleaning up resources...");
}
}
5. Create the DatabaseService Class
DatabaseService.java
package net.javaguides.spring;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;
import org.springframework.stereotype.Component;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.Statement;
@Component
public class DatabaseService {
private final DataSource dataSource;
public DatabaseService(DataSource dataSource) {
this.dataSource = dataSource;
}
@PostConstruct
public void initDatabase() {
try (Connection connection = dataSource.getConnection();
Statement statement = connection.createStatement()) {
statement.execute("CREATE TABLE IF NOT EXISTS Users (id INT AUTO_INCREMENT, name VARCHAR(255), PRIMARY KEY (id))");
statement.execute("INSERT INTO Users (name) VALUES ('John Doe')");
System.out.println("PostConstruct: Database initialized");
} catch (Exception e) {
e.printStackTrace();
}
}
@PreDestroy
public void cleanupDatabase() {
try (Connection connection = dataSource.getConnection();
Statement statement = connection.createStatement()) {
statement.execute("DROP TABLE IF EXISTS Users");
System.out.println("PreDestroy: Database cleaned up");
} catch (Exception e) {
e.printStackTrace();
}
}
}
6. Create the AppConfig Class
AppConfig.java
package net.javaguides.spring;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@ComponentScan(basePackages = "net.javaguides.spring")
public class AppConfig {
}
7. Create the Main Application Class
Application.java
package net.javaguides.spring;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
public class Application {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
MessageService messageService = context.getBean(MessageService.class);
System.out.println("Message from MessageService: " + messageService.getMessage());
context.close();
}
}
In this class:
AnnotationConfigApplicationContextis used to create and manage the Spring application context.context.getBean(MessageService.class)retrieves a bean of typeMessageServicefrom the Spring context.- The
closemethod oncontexttriggers the@PreDestroymethod.
Running the Application
When you run the Application class, you should see the following output:
PostConstruct: Database initialized
PostConstruct: MessageService initialized with message: Hello, Spring!
Message from MessageService: Hello, Spring!
PreDestroy: Cleaning up resources...
PreDestroy: Database cleaned up
Explanation:
- The
initDatabasemethod is called after theDatabaseServicebean is initialized, setting up the database and inserting initial data. - The
initmethod is called after theMessageServiceImplbean is initialized, setting the message and printing the initialization message. - The
getMessagemethod prints the message to the console. - The
cleanupmethod is called before theMessageServiceImplbean is destroyed, cleaning up any resources. - The
cleanupDatabasemethod is called before theDatabaseServicebean is destroyed, dropping the database table.
Conclusion
In this article, we demonstrated how to use the @PostConstruct and @PreDestroy annotations in a Spring Boot application. By using these annotations, we can perform initialization and cleanup tasks for our beans. The example showed how to initialize a database at startup and clean up resources when the application shuts down, which is a common real-world use case.
Comments
Post a Comment
Leave Comment