DEV Community

Hunor Vadasz-Perhat
Hunor Vadasz-Perhat

Posted on • Edited on

πŸ“Œ spring-note-003: Spring Bean Lifecycle

πŸ”Ή 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.

Top comments (0)