Bean Lifecycle Hooks
Bean Hooks = extension points where you can plug custom logic into the bean lifecycle.
This allows you to:
- modify beans before/after initialization
- add cross-cutting behavior (logging, proxies, etc)
Where hooks fit in lifecycle
BeanPostProcessor
Allows you to intercept every bean:
- before initialization
- after initialization
@Component
class CustomBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) {
System.out.println("Before Init: " + beanName);
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
System.out.println("After Init: " + beanName);
return bean;
}
}
Real Use Case
You can modify or wrap beans:
@Override
public Object postProcessAfterInitialization(Object bean, String name) {
if (bean instanceof MessageService) {
System.out.println("Wrapping MessageService");
}
return bean;
}
This is how:
- AOP works
- @Transactional works
- proxy are created
Full Example
package com.example.demo;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;
import jakarta.annotation.PostConstruct;
public class Main {
public static void main(String[] args) {
AnnotationConfigApplicationContext context =
new AnnotationConfigApplicationContext(AppConfig.class);
MyService s = context.getBean(MyService.class);
s.run();
context.close();
}
}
@Configuration
@ComponentScan
class AppConfig {}
@Component
class MyService {
public MyService() {
System.out.println("1. Constructor");
}
@PostConstruct
public void init() {
System.out.println("2. @PostConstruct");
}
public void run() {
System.out.println("3. Running ...");
}
}
@Component
class CustomBeanPostProcessor implements BeanPostProcessor {
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) {
System.out.println("Before Init: " + beanName);
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
System.out.println("After Init: " + beanName);
return bean;
}
}
Best Practices