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
-
Annotation-based
@Component public class Engine { }
-
@Component
,@Service
,@Repository
,@Controller
→ all mark a class as a bean. -
These are discovered automatically with component scanning.
-
-
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.
-
-
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
intoCar
. - 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.