Comprehensive Guide to the Spring Bean Lifecycle: Detailed Stages and Processes

The lifecycle of a Spring bean involves several stages, from instantiation to destruction, managed by the Spring IoC (Inversion of Control) container. Understanding this lifecycle is crucial for effectively utilizing Spring’s capabilities and for implementing custom initialization and destruction logic.

1. Bean Definition

Before the Spring IoC container can create and manage beans, it needs to know their definitions. Beans can be defined in various ways:

  • XML Configuration: Using <bean> elements in XML configuration files.
  • Java Configuration: Using @Configuration and @Bean annotations.
  • Component Scanning: Using @Component, @Service, @Repository, and @Controller annotations.

2. Bean Instantiation

The container instantiates the bean using the no-argument constructor or a constructor specified in the configuration.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
@Bean
public MyBean myBean() {
return new MyBean();
}
@Bean public MyBean myBean() { return new MyBean(); }
@Bean
public MyBean myBean() {
    return new MyBean();
}

 


3. Populate Properties

After instantiation, the container injects dependencies as specified in the bean definition. This is done through:

  • Constructor Injection
  • Setter Injection
  • Field Injection
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
@Service
public class MyService {
@Autowired
private MyRepository myRepository;
public MyService(MyRepository myRepository) {
this.myRepository = myRepository;
}
@Autowired
public void setMyRepository(MyRepository myRepository) {
this.myRepository = myRepository;
}
}
@Service public class MyService { @Autowired private MyRepository myRepository; public MyService(MyRepository myRepository) { this.myRepository = myRepository; } @Autowired public void setMyRepository(MyRepository myRepository) { this.myRepository = myRepository; } }
@Service
public class MyService {
    @Autowired
    private MyRepository myRepository;

    public MyService(MyRepository myRepository) {
        this.myRepository = myRepository;
    }

    @Autowired
    public void setMyRepository(MyRepository myRepository) {
        this.myRepository = myRepository;
    }
}

 


4. Set Bean Name

The BeanNameAware interface allows the bean to be aware of its name defined in the container.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
public class MyBean implements BeanNameAware {
@Override
public void setBeanName(String name) {
System.out.println("Bean name is: " + name);
}
}
public class MyBean implements BeanNameAware { @Override public void setBeanName(String name) { System.out.println("Bean name is: " + name); } }
public class MyBean implements BeanNameAware {
    @Override
    public void setBeanName(String name) {
        System.out.println("Bean name is: " + name);
    }
}

 

See also  Understanding Profiles in Spring Boot


5. Set Bean Factory

The BeanFactoryAware interface allows the bean to be aware of its BeanFactory.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
public class MyBean implements BeanFactoryAware {
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
System.out.println("BeanFactory is: " + beanFactory);
}
}
public class MyBean implements BeanFactoryAware { @Override public void setBeanFactory(BeanFactory beanFactory) throws BeansException { System.out.println("BeanFactory is: " + beanFactory); } }
public class MyBean implements BeanFactoryAware {
    @Override
    public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
        System.out.println("BeanFactory is: " + beanFactory);
    }
}

 


6. Set Application Context

The ApplicationContextAware interface allows the bean to be aware of its ApplicationContext.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
public class MyBean implements ApplicationContextAware {
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
System.out.println("ApplicationContext is: " + applicationContext);
}
}
public class MyBean implements ApplicationContextAware { @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { System.out.println("ApplicationContext is: " + applicationContext); } }
public class MyBean implements ApplicationContextAware {
    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        System.out.println("ApplicationContext is: " + applicationContext);
    }
}

 


7. Pre-initialization (Bean Post Processors)

BeanPostProcessor allows for custom modification of new bean instances before and after initialization.

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
public class CustomBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("Before Initialization : " + beanName);
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("After Initialization : " + beanName);
return bean;
}
}
public class CustomBeanPostProcessor implements BeanPostProcessor { @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { System.out.println("Before Initialization : " + beanName); return bean; } @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { System.out.println("After Initialization : " + beanName); return bean; } }
public class CustomBeanPostProcessor implements BeanPostProcessor {
    @Override
    public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("Before Initialization : " + beanName);
        return bean;
    }

    @Override
    public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        System.out.println("After Initialization : " + beanName);
        return bean;
    }
}

 


8. Initialization Callbacks

  • InitializingBean Interface: The afterPropertiesSet method is called after the properties are set.
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
public class MyBean implements InitializingBean {
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("InitializingBean afterPropertiesSet method called");
}
}
public class MyBean implements InitializingBean { @Override public void afterPropertiesSet() throws Exception { System.out.println("InitializingBean afterPropertiesSet method called"); } }
public class MyBean implements InitializingBean {
    @Override
    public void afterPropertiesSet() throws Exception {
        System.out.println("InitializingBean afterPropertiesSet method called");
    }
}

 


  • Custom Init Method: You can specify a custom init method in the bean configuration.
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
@Bean(initMethod = "customInit")
public MyBean myBean() {
return new MyBean();
}
public class MyBean {
public void customInit() {
System.out.println("Custom init method called");
}
}
@Bean(initMethod = "customInit") public MyBean myBean() { return new MyBean(); } public class MyBean { public void customInit() { System.out.println("Custom init method called"); } }
@Bean(initMethod = "customInit")
public MyBean myBean() {
    return new MyBean();
}

public class MyBean {
    public void customInit() {
        System.out.println("Custom init method called");
    }
}

 

See also  Understanding Spring Boot Architecture


  • @PostConstruct Annotation: The method annotated with @PostConstruct is called after dependencies are injected.
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
public class MyBean {
@PostConstruct
public void init() {
System.out.println("PostConstruct init method called");
}
}
public class MyBean { @PostConstruct public void init() { System.out.println("PostConstruct init method called"); } }
public class MyBean {
    @PostConstruct
    public void init() {
        System.out.println("PostConstruct init method called");
    }
}

 


9. Post-initialization (Bean Post Processors)

Same as step 7, BeanPostProcessor is used for further customization after initialization.

10. Ready to Use

At this point, the bean is fully initialized, dependencies are set, and it is ready for use by the application.

11. Destruction Callbacks

  • DisposableBean Interface: The destroy method is called during bean destruction.
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
public class MyBean implements DisposableBean {
@Override
public void destroy() throws Exception {
System.out.println("DisposableBean destroy method called");
}
}
public class MyBean implements DisposableBean { @Override public void destroy() throws Exception { System.out.println("DisposableBean destroy method called"); } }
public class MyBean implements DisposableBean {
    @Override
    public void destroy() throws Exception {
        System.out.println("DisposableBean destroy method called");
    }
}

 


  • Custom Destroy Method: You can specify a custom destroy method in the bean configuration.
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
@Bean(destroyMethod = "customDestroy")
public MyBean myBean() {
return new MyBean();
}
public class MyBean {
public void customDestroy() {
System.out.println("Custom destroy method called");
}
}
@Bean(destroyMethod = "customDestroy") public MyBean myBean() { return new MyBean(); } public class MyBean { public void customDestroy() { System.out.println("Custom destroy method called"); } }
@Bean(destroyMethod = "customDestroy")
public MyBean myBean() {
    return new MyBean();
}

public class MyBean {
    public void customDestroy() {
        System.out.println("Custom destroy method called");
    }
}

 


  • @PreDestroy Annotation: The method annotated with @PreDestroy is called before bean destruction.
Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
public class MyBean {
@PreDestroy
public void destroy() {
System.out.println("PreDestroy destroy method called");
}
}
public class MyBean { @PreDestroy public void destroy() { System.out.println("PreDestroy destroy method called"); } }
public class MyBean {
    @PreDestroy
    public void destroy() {
        System.out.println("PreDestroy destroy method called");
    }
}


Summary

The Spring bean lifecycle involves a series of well-defined stages from creation to destruction. By leveraging these stages, you can hook into the lifecycle of your beans to perform custom initialization and cleanup operations. The lifecycle stages include:

  1. Bean Definition: Declaring how beans are configured.
  2. Bean Instantiation: Creating bean instances.
  3. Populate Properties: Injecting dependencies.
  4. Set Bean Name: Bean name awareness.
  5. Set Bean Factory: Bean factory awareness.
  6. Set Application Context: Application context awareness.
  7. Pre-initialization (Bean Post Processors): Customizing beans before initialization.
  8. Initialization Callbacks: Custom init methods.
  9. Post-initialization (Bean Post Processors): Customizing beans after initialization.
  10. Ready to Use: Beans are fully initialized.
  11. Destruction Callbacks: Custom destroy methods.
See also  In-Depth Guide to Mastering Spring Security: Comprehensive Overview and Practical Implementation

Understanding and utilizing these stages allows for more effective and efficient use of Spring beans within your applications.

Leave a Reply

Your email address will not be published. Required fields are marked *

Get a Quote

Give us a call or fill in the form below and we will contact you. We endeavor to answer all inquiries within 24 hours on business days.