Table of Contents
- Introduction to Component Scanning
- Default Component Scanning Behavior
- Customizing Component Scanning
- Spring Bean Lifecycle Overview
- Bean Initialization and Destruction
- Bean Lifecycle Hooks:
@PostConstruct
and@PreDestroy
- Using
InitializingBean
andDisposableBean
Interfaces - Using
@Bean
withinitMethod
anddestroyMethod
- Lifecycle Annotations vs Interfaces
- Best Practices
- Conclusion
1. Introduction to Component Scanning
Spring Boot uses Component Scanning to automatically detect and register beans (classes) into the application context based on annotations. This mechanism reduces boilerplate configuration and allows Spring to manage your classes as beans without explicit XML or Java-based registration.
2. Default Component Scanning Behavior
By default, Spring Boot scans for components (like @Component
, @Service
, @Repository
, and @Controller
) in the same package as the main application class and its sub-packages.
Example:
javaCopyEdit@SpringBootApplication
public class MyApp {
public static void main(String[] args) {
SpringApplication.run(MyApp.class, args);
}
}
If MyApp
is in the package com.example
, Spring will scan com.example
and all its sub-packages automatically.
3. Customizing Component Scanning
To scan additional packages or control scanning behavior, use @ComponentScan
:
javaCopyEdit@SpringBootApplication
@ComponentScan(basePackages = {"com.example.services", "com.example.controllers"})
public class MyApp { }
You can also exclude or include components based on annotations or custom filters:
javaCopyEdit@ComponentScan(
basePackages = "com.example",
excludeFilters = @ComponentScan.Filter(type = FilterType.ANNOTATION, classes = Deprecated.class)
)
4. Spring Bean Lifecycle Overview
A Spring Bean is an object managed by the Spring IoC (Inversion of Control) container. The lifecycle of a bean includes:
- Instantiation
- Dependency Injection (Population)
- Custom Initialization
- Usage
- Custom Destruction
5. Bean Initialization and Destruction
Spring provides multiple ways to hook into the bean lifecycle:
- Annotation-based (
@PostConstruct
,@PreDestroy
) - Interface-based (
InitializingBean
,DisposableBean
) - XML-based (not commonly used in Spring Boot)
- Java config using
@Bean(initMethod, destroyMethod)
6. Bean Lifecycle Hooks: @PostConstruct
and @PreDestroy
These annotations are used on methods that should run after dependency injection and before bean destruction:
javaCopyEdit@Component
public class MyService {
@PostConstruct
public void init() {
System.out.println("Bean is going through init.");
}
@PreDestroy
public void destroy() {
System.out.println("Bean will be destroyed.");
}
}
Requirements:
- Must be void
- No parameters
- Only one method per annotation
7. Using InitializingBean
and DisposableBean
Interfaces
These are older but still valid ways to handle lifecycle events:
javaCopyEdit@Component
public class MyService implements InitializingBean, DisposableBean {
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("InitializingBean: afterPropertiesSet called.");
}
@Override
public void destroy() throws Exception {
System.out.println("DisposableBean: destroy called.");
}
}
These are interface-based, which may reduce flexibility compared to annotations.
8. Using @Bean
with initMethod
and destroyMethod
If you’re using Java-based configuration and defining beans with @Bean
, you can specify lifecycle methods directly:
javaCopyEdit@Configuration
public class AppConfig {
@Bean(initMethod = "init", destroyMethod = "cleanup")
public MyBean myBean() {
return new MyBean();
}
}
Inside MyBean
:
javaCopyEditpublic class MyBean {
public void init() {
System.out.println("Init method called.");
}
public void cleanup() {
System.out.println("Destroy method called.");
}
}
9. Lifecycle Annotations vs Interfaces
Feature | @PostConstruct/@PreDestroy | InitializingBean/DisposableBean |
---|---|---|
Style | Declarative (Annotation) | Programmatic (Interface) |
Preferred in Spring Boot | ✅ Yes | ❌ Less preferred |
Testable | ✅ Better | ⚠️ Coupled to Spring API |
Flexibility | ✅ High | ⚠️ Low (must implement interfaces) |
10. Best Practices
- Use
@PostConstruct
and@PreDestroy
for cleaner code and better decoupling. - Avoid field injection and prefer constructor injection for lifecycle-safe design.
- Minimize bean lifecycle logic and move business logic into proper service layers.
- Use
@ComponentScan
sparingly to avoid unnecessarily loading unwanted components.
11. Conclusion
Understanding Component Scanning and the Bean Lifecycle is essential when working with Spring Boot. These concepts ensure that your application is both modular and maintainable, while taking full advantage of Spring’s powerful dependency injection and lifecycle management capabilities.