Spring Bean Lifecycle

 

What is a Spring Bean?

  • A Spring Bean is simply an object that is managed by the Spring IoC container.
  • In other words: any Java object that you register with Spring (either explicitly or via annotations) becomes a bean.
  • Spring takes care of:
    • Creating it
    • Injecting its dependencies
    • Managing its lifecycle (init → use → destroy)

How a class becomes a Spring Bean

  1. Annotation-based

    @Component
    public class Engine {
    }
    
    • @Component, @Service, @Repository, @Controller → all mark a class as a bean.

    • These are discovered automatically with component scanning.

  2. Via @Bean in Configuration

    @Configuration
    public class AppConfig {
        @Bean
        public Engine engine() {
            return new Engine();
        }
    }
    
    • This way you explicitly tell Spring how to create the bean.

  3. XML (old style)

    <bean id="engine" class="com.example.Engine"/>
    

Example in Action

@Component
class Engine {
   public void start() { System.out.println("Engine started!"); }
}

@Component
class Car {
   private final Engine engine;
   public Car(Engine engine) { this.engine = engine; } // injected automatically
}

Spring will:

  • Create a bean of type Engine.
  • Create a bean of type Car.
  • Inject Engine into Car.
  • Manage their lifecycle.

In short:


A Spring Bean = any object created, configured, and managed by the Spring IoC container.


You don’t call new Car() yourself → Spring does it for you, and wires dependencies.

Spring Bean Lifecycle

 

When you define a bean in Spring, the IoC container manages its creation, initialization, usage, and destruction.


1. Bean Definition

  • You declare a bean using @Component, @Service, @Repository, or via @Bean inside a @Configuration.
  • Spring stores this as a BeanDefinition in the container.

2. Instantiation

  • Spring creates an object of the bean using its constructor (default or parameterized).

@Component

class Engine {

public Engine()

{ System.out.println("Engine constructor called"); } }


3. Populate Properties (Dependency Injection)

  • Spring injects dependencies (via constructor, setter, or field).
@Component
class Car {
   private final Engine engine;
   public Car(Engine engine) { this.engine = engine; }
}

4. BeanNameAware / BeanFactoryAware (Optional)

  • If bean implements these Aware interfaces, container passes its name and reference to BeanFactory.

5. BeanPostProcessors (Before Initialization)

  • Any registered BeanPostProcessor gets a chance to modify the bean before initialization.

6. Initialization Callbacks

  • @PostConstruct annotated method is called.
  • OR if bean implements InitializingBean.afterPropertiesSet(), that method runs.
  • OR if you specified a custom initMethod in @Bean(initMethod="...").
    • @Component class Driver { @PostConstruct public void init() { System.out.println("Driver is ready!"); } } 

7. BeanPostProcessors (After Initialization)

  • Another chance to wrap/modify the bean (e.g., AOP proxies are created here).


8. Ready for Use

  • Now the bean is available for the application to use.


9. Destruction Callbacks

  • When the container shuts down:

  • @PreDestroy runs.
  • OR DisposableBean.destroy() if implemented.
  • OR @Bean(destroyMethod="...").
@Component
class Driver {
   @PreDestroy
   public void cleanup() {
      System.out.println("Driver bean cleanup...");
   }
}

Lifecycle Flow (Summary)

Instantiation → Dependency Injection → 
BeanNameAware/BeanFactoryAware → 
BeanPostProcessor (before init) → 
@PostConstruct / afterPropertiesSet() / custom init → 
BeanPostProcessor (after init) → 
Bean ready to use → 
@PreDestroy / destroy() / custom destroy

👉 In Spring Boot, all these steps are handled by the ApplicationContext.

Back to blog

Leave a comment