📌 spring-note-003: Spring Bean Lifecycle

Hunor Vadasz-Perhat - Feb 11 - - Dev Community

🔹 What is the Spring Bean Lifecycle?

💡 Spring Beans go through multiple phases: creation, initialization, usage, and destruction.

💡 Spring provides hooks to customize these phases (e.g., @PostConstruct, @PreDestroy).


📌 Phases of the Spring Bean Lifecycle

🔥 Step by Step Breakdown:

1️⃣ Bean Instantiation → Spring creates the bean instance.

2️⃣ Populate Properties (Dependency Injection) → Spring injects dependencies.

3️⃣ Bean Name is Set (BeanNameAware#setBeanName())

4️⃣ Bean Factory is Set (BeanFactoryAware#setBeanFactory())

5️⃣ ApplicationContext is Set (ApplicationContextAware#setApplicationContext())

6️⃣ Before Initialization Processing (BeanPostProcessor#postProcessBeforeInitialization())

7️⃣ Custom Initialization Methods:

  • InitializingBean#afterPropertiesSet()
  • @PostConstruct
  • init-method (if specified in XML or @Bean)

8️⃣ After Initialization Processing (BeanPostProcessor#postProcessAfterInitialization())

9️⃣ Bean is Ready for Use! 🚀

🔟 Before Destruction Processing (DestructionAwareBeanPostProcessor#postProcessBeforeDestruction())

1️⃣1️⃣ Custom Destruction Methods:

  • DisposableBean#destroy()
  • @PreDestroy
  • destroy-method (if specified in XML or @Bean)

1️⃣2️⃣ Bean is Removed (Garbage Collected).

🔥 This entire process is controlled by Spring’s ApplicationContext!


📌 Hands-On Project: Bean Lifecycle in Action

💡 Let’s create a small Spring Boot app to observe and control the Bean Lifecycle.


Step 1: Create a Spring Boot Project

1️⃣ Go to Spring Initializr

2️⃣ Select:

  • Spring Boot Version: Latest stable
  • Dependencies: Spring Web
  • Packaging: Jar 3️⃣ Click Generate and extract the zip file.

Step 2: Define a Bean with Lifecycle Hooks

📌 Create a Pirate Bean with Lifecycle Annotations:

package com.example.lifecycle;

import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;
import org.springframework.stereotype.Component;

@Component
public class Pirate {

    public Pirate() {
        System.out.println("⚓ Pirate Bean Instantiated!");
    }

    @PostConstruct
    public void prepareForSailing() {
        System.out.println("🏴‍☠️ @PostConstruct: Pirate is ready for adventure!");
    }

    @PreDestroy
    public void retireFromSailing() {
        System.out.println("☠️ @PreDestroy: Pirate is retiring...");
    }
}
Enter fullscreen mode Exit fullscreen mode

💡 What happens here?
Pirate() → Constructor is called (bean instantiation).

@PostConstruct → Called after dependencies are injected but before the bean is used.

@PreDestroy → Called before the bean is destroyed (removed from context).


Step 3: Add BeanPostProcessor to Track Lifecycle Events

📌 Create a PirateLifecycleLogger to observe Spring’s lifecycle hooks:

package com.example.lifecycle;

import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.stereotype.Component;

@Component
public class PirateLifecycleLogger implements BeanPostProcessor {

    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) {
        System.out.println("⏳ Before Initialization: " + beanName);
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) {
        System.out.println("✅ After Initialization: " + beanName);
        return bean;
    }
}
Enter fullscreen mode Exit fullscreen mode

💡 What happens here?
postProcessBeforeInitialization() runs before @PostConstruct and afterPropertiesSet().

postProcessAfterInitialization() runs after initialization but before usage.


Step 4: Create the Main Application Class

📌 Modify SpringBootApplication to trigger the lifecycle:

package com.example.lifecycle;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ConfigurableApplicationContext;

@SpringBootApplication
public class LifecycleApplication {
    public static void main(String[] args) {
        ConfigurableApplicationContext context = SpringApplication.run(LifecycleApplication.class, args);

        System.out.println("🛳️ Application is Running...");

        // Close context to trigger @PreDestroy
        context.close();
    }
}
Enter fullscreen mode Exit fullscreen mode

💡 Why context.close()?

It manually shuts down the Spring application, triggering @PreDestroy!


Step 5: Run the Application

💡 Run the app using:

mvn spring-boot:run
Enter fullscreen mode Exit fullscreen mode

or

./mvnw spring-boot:run
Enter fullscreen mode Exit fullscreen mode

👀 Expected Output:

⚓ Pirate Bean Instantiated!
⏳ Before Initialization: pirate
🏴‍☠️ @PostConstruct: Pirate is ready for adventure!
✅ After Initialization: pirate
🛳️ Application is Running...
☠️ @PreDestroy: Pirate is retiring...
Enter fullscreen mode Exit fullscreen mode

🔥 Boom! You just witnessed the Spring Bean Lifecycle in action!


📌 Summary of Step 3

Spring Beans have a lifecycle controlled by ApplicationContext.

Spring calls lifecycle methods like @PostConstruct and @PreDestroy.

BeanPostProcessor allows custom pre/post-initialization logic.

context.close() manually triggers destruction lifecycle.


📌 Topics Covered in This Section
📜 Spring Bean Lifecycle (✔️ Covered)

  • How Beans are created & destroyed (Instantiation → Initialization → Destruction).

  • Lifecycle methods:

    • @PostConstruct (Runs after properties are set).
    • @PreDestroy (Runs before bean destruction).
  • BeanPostProcessor Hooks:

    • postProcessBeforeInitialization()
    • postProcessAfterInitialization()
  • Manually closing the ApplicationContext (context.close()).

🔥 Key Takeaways to Remember:
✅ Spring manages bean lifecycles automatically using ApplicationContext.
✅ @PostConstruct and @PreDestroy are commonly used for lifecycle management.
✅ BeanPostProcessor allows customization before/after initialization.
✅ Manually closing the ApplicationContext triggers @PreDestroy.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .