Skip to content

Kunal70616c/bean-lifecycle-mechanics

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Bean Lifecycle Mechanics

A comprehensive demonstration of Spring Bean Lifecycle using manual method implementations in Java.

📋 Overview

This project demonstrates the complete lifecycle of a Spring Bean by implementing various lifecycle interfaces and callbacks. It shows how Spring manages beans from creation to destruction, providing hooks at each stage for custom initialization and cleanup logic.

🔄 What is Bean Lifecycle?

The Spring Bean Lifecycle refers to the series of stages a bean goes through from its instantiation to its destruction. Spring provides multiple ways to hook into this lifecycle, allowing developers to execute custom code at specific points.

Bean Lifecycle Stages

1. Bean Instantiation
2. Populate Properties
3. BeanNameAware's setBeanName()
4. BeanFactoryAware's setBeanFactory()
5. ApplicationContextAware's setApplicationContext()
6. BeanPostProcessor's postProcessBeforeInitialization()
7. InitializingBean's afterPropertiesSet()
8. Custom init-method
9. BeanPostProcessor's postProcessAfterInitialization()
   ↓
   [Bean Ready for Use]
   ↓
10. @PreDestroy annotation method
11. DisposableBean's destroy()
12. Custom destroy-method

🏗️ Project Structure

sh.surge.kunal.banking/
├── configurations/
│   ├── AppConfig.java                    # Spring configuration with bean definitions
│   └── CustomerBeanPostProcessor.java    # Custom BeanPostProcessor implementation
├── models/
│   ├── Address.java                      # Address model
│   ├── Customer.java                     # Main bean demonstrating lifecycle
│   └── FullName.java                     # FullName model
└── utils/
    └── CustomerApp.java                  # Application entry point

🎯 How This Project Implements Bean Lifecycle

1. Customer Bean (Customer.java)

The Customer class implements multiple Spring lifecycle interfaces to demonstrate each stage:

  • BeanNameAware: Receives the bean name from the container
  • BeanFactoryAware: Gets access to the BeanFactory
  • ApplicationContextAware: Gets access to the ApplicationContext
  • InitializingBean: Executes initialization logic after properties are set
  • DisposableBean: Executes cleanup logic before bean destruction
// Step 1: Bean Name Awareness
@Override
public void setBeanName(String name) {
    logger.info("1. Bean Name is set in Customer Bean: " + name);
}

// Step 2: Bean Factory Awareness
@Override
public void setBeanFactory(BeanFactory beanFactory) {
    logger.info("2. Bean Factory is set in Customer Bean");
}

// Step 3: Application Context Awareness
@Override
public void setApplicationContext(ApplicationContext applicationContext) {
    logger.info("3. Application Context is set in Customer Bean");
}

// Step 4: After Properties Set
@Override
public void afterPropertiesSet() {
    logger.info("4. Customer Bean is initialized");
}

// Step 5: Custom Init Method
public void customInit() {
    logger.info("5. Custom Init method called for Customer Bean");
}

// Step 6: Pre Destroy
@PreDestroy
public void preDestroy() {
    logger.info("6. Pre Destroy method called for Customer Bean");
}

// Step 7: Destroy Interface
@Override
public void destroy() {
    logger.info("7. Customer Bean is destroyed");
}

// Step 8: Custom Destroy Method
public void customDestroy() {
    logger.info("8. Custom Destroy method called for Customer Bean");
}

2. Configuration (AppConfig.java)

Defines the Customer bean with custom init and destroy methods:

@Bean(initMethod = "customInit", destroyMethod = "customDestroy")
public Customer customer() {
    // Bean creation with Faker library for dummy data
    Faker faker = new Faker();
    Customer customer = new Customer();
    // ... property initialization
    return customer;
}

3. BeanPostProcessor (CustomerBeanPostProcessor.java)

Intercepts bean initialization to add custom logic before and after initialization:

@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) {
    if(bean instanceof Customer) {
        logger.info("Customer Bean is about to be initialized: " + beanName);
    }
    return bean;
}

@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
    if(bean instanceof Customer) {
        logger.info("Customer Bean has been initialized: " + beanName);
    }
    return bean;
}

4. Application Runner (CustomerApp.java)

Demonstrates the complete lifecycle by creating and closing the application context:

// Create context - triggers bean creation and initialization
AnnotationConfigApplicationContext context = 
    new AnnotationConfigApplicationContext(AppConfig.class);

// Get and use the bean
Customer customer = context.getBean(Customer.class);
logger.info("Customer Details: " + customer);

// Close context - triggers bean destruction
context.close();

🚀 Running the Project

  1. Ensure you have Java 17+ and Maven installed
  2. Run the CustomerApp.java class
  3. Observe the console output showing the complete bean lifecycle

Expected Output Sequence

1. Bean Name is set in Customer Bean: customer
2. Bean Factory is set in Customer Bean
3. Application Context is set in Customer Bean
   Customer Bean is about to be initialized: customer
4. Customer Bean is initialized
5. Custom Init method called for Customer Bean
   Customer Bean has been initialized: customer
   Customer Details: [Customer object details]
6. Pre Destroy method called for Customer Bean
7. Customer Bean is destroyed
8. Custom Destroy method called for Customer Bean

📚 Key Concepts Demonstrated

  • Lifecycle Interfaces: BeanNameAware, BeanFactoryAware, ApplicationContextAware, InitializingBean, DisposableBean
  • Custom Callbacks: init-method and destroy-method attributes
  • Annotations: @PreDestroy for pre-destruction callbacks
  • BeanPostProcessor: Custom processing before and after initialization
  • Configuration: Java-based configuration with @Configuration and @Bean

🛠️ Dependencies

  • Spring Framework (Core, Context, Beans)
  • Lombok (for reducing boilerplate code)
  • JavaFaker (for generating test data)
  • SLF4J (for logging)

💡 Use Cases

This pattern is useful for:

  • Resource initialization (database connections, file handles)
  • Configuration validation
  • Resource cleanup and connection closing
  • Custom logging and monitoring
  • Cache warming
  • External service initialization

📝 Notes

  • All lifecycle methods are called in a specific order by the Spring container
  • BeanPostProcessor methods are called for all beans in the container
  • Custom init/destroy methods can have any name but must be specified in @Bean annotation
  • @PreDestroy is called before DisposableBean.destroy()

Author: Kunal
Purpose: Educational demonstration of Spring Bean Lifecycle

About

A deep-dive technical demonstration of the Spring Bean Lifecycle, focusing on manual configuration hooks and callback mechanisms. This repository bypasses the "magic" of auto-configuration to show exactly how developers can intervene at every stage of a bean's life—from instantiation to destruction.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Contributors

Languages