「Spring Boot #3」 Spring Bean Life Cycle + @PostConstruct and @PreDestroy
In the previous articles, you've gained an understanding of the basic concepts of Bean and how to inject them in Spring Boot using @Component + @Autowired.
1. [「Spring Boot #1」Guide to @Component and @Autowired ] 2. [「Spring Boot #2」Guide to @Autowired - @Primary - @Qualifier]
Today, we will delve deeper into the lifecycle of a Bean.
Installation:
<?xml version="1.0" encoding="UTF-8"?> <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 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>3.2.1</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.blogspot.amztopfind</groupId> <artifactId>spring-boot-tutorial</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>pom</packaging> <name>spring-boot-tutorial</name> <description>Everything about Spring Boot</description> <properties> <java.version>21</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
Directory Structure:
@Component public class Girl { @PostConstruct public void postConstruct(){ System.out.println("\t>> The Girl object will run this method after being fully initialized."); } }
@PreDestroy
@PreDestroy is annotated on a specific method within a Bean. The IoC Container or ApplicationContext will invoke this method before a Bean is destroyed or no longer managed.
@Component public class Girl { @PreDestroy public void preDestroy(){ System.out.println("\t>> The Girl object runs this method before being destroyed."); } }
Bean Life Cycle
From the first run until shutdown, Spring Boot manages the lifecycle of the Beans, as illustrated in the image below:
@Component public class Girl { @PostConstruct public void postConstruct(){ System.out.println("\t>> The Girl object will run this method after being fully initialized."); } @PreDestroy public void preDestroy(){ System.out.println("\t>> The Girl object runs this method before being destroyed."); } }
Print to the screen during the entire lifecycle of Spring Boot from the first run until shutdown:
package com.blogspot.amztopfind.beanlifecycle; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ApplicationContext; import org.springframework.context.ConfigurableApplicationContext; @SpringBootApplication public class App { public static void main(String[] args) { // ApplicationContext is the container that holds all Beans System.out.println("> Before IoC Container is initialized"); ApplicationContext context = SpringApplication.run(App.class, args); System.out.println("> After IoC Container is initialized"); // After running, the context will contain Beans marked with @Component. Girl girl = context.getBean(Girl.class); System.out.println("> Before IoC Container destroys Girl"); ((ConfigurableApplicationContext) context).getBeanFactory().destroyBean(girl); System.out.println("> After IoC Container destroys Girl"); } }
Output:
> Before IoC Container is initialized > Before IoC Container is initialized >> The Girl object will run this method after being fully initialized. > After IoC Container is initialized > Before IoC Container destroys Girl >> The Girl object runs this method before being destroyed. > After IoC Container destroys Girl
You will see the line 'Before IoC Container is initialized' being executed twice.
This happens because the App.main(args) method is executed twice!
The first time is when we run it.
The second time is when Spring Boot runs after being called with SpringApplication.run(App.class, args). This is when the IoC Container (ApplicationContext
) is created and looks for Bean.
Meaning:
@PostConstruct and @PreDestroy are two highly meaningful annotations. If you grasp the lifecycle of a Bean, you can leverage them to perform specific tasks such as setting, adding default values to properties after creation, deleting data before destruction, etc. Many other functionalities can be implemented based on your needs.