Comprehensive Overview of Spring & Spring Boot Extension Points and Bean Lifecycle
This article provides a detailed summary of Spring and Spring Boot's bean lifecycle, enumerating all major extension interfaces—including ApplicationContextInitializer, BeanDefinitionRegistryPostProcessor, BeanFactoryPostProcessor, InstantiationAwareBeanPostProcessor, SmartInstantiationAwareBeanPostProcessor, various Aware interfaces, FactoryBean, CommandLineRunner, and ApplicationListener—along with usage scenarios and code examples, enabling developers to customize bean initialization and container behavior.
1. Background
Spring's core concept is a container; when the container refreshes, the internal processes are complex. Spring Boot further encapsulates Spring, following convention‑over‑configuration and providing auto‑configuration, so that adding a dependency often results in a functional feature with almost zero configuration. Understanding the bean construction lifecycle and the various extension interfaces is essential for writing middleware and reusable libraries.
2. Extension Point Call Sequence Diagram
The following diagram (illustrated in the original article) shows the order in which all extensible points are invoked during a bean's lifecycle within the Spring container.
3. ApplicationContextInitializer
org.springframework.context.ApplicationContextInitializer
This callback is invoked before the Spring container is refreshed. Implementations can run custom logic before any beans are instantiated, such as activating configurations or performing byte‑code manipulation.
Typical registration methods:
Programmatically via springApplication.addInitializers(new MyInitializer())
In application.properties with context.initializer.classes=com.example.MyInitializer
Via Spring SPI by adding org.springframework.context.ApplicationContextInitializer=com.example.MyInitializer to spring.factories
public class MyInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
System.out.println("[ApplicationContextInitializer]");
}
}4. BeanDefinitionRegistryPostProcessor
org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor
Executed after bean definitions are read, allowing dynamic registration of additional bean definitions, even from outside the classpath.
public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
System.out.println("[BeanDefinitionRegistryPostProcessor] postProcessBeanDefinitionRegistry");
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
System.out.println("[BeanDefinitionRegistryPostProcessor] postProcessBeanFactory");
}
}5. BeanFactoryPostProcessor
org.springframework.beans.factory.config.BeanFactoryPostProcessor
Runs after bean definitions are loaded but before any bean instances are created, enabling modification of bean definition metadata.
public class MyBeanFactoryPostProcessor implements BeanFactoryPostProcessor {
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
System.out.println("[BeanFactoryPostProcessor]");
}
}6. InstantiationAwareBeanPostProcessor
org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor
Extends BeanPostProcessor with three additional methods covering the instantiation phase and property injection phase, useful for tasks such as custom bean creation, property value manipulation, or collecting beans of a certain type.
public class MyInstantiationAwareBeanPostProcessor implements InstantiationAwareBeanPostProcessor {
@Override
public Object postProcessBeforeInstantiation(Class
beanClass, String beanName) throws BeansException {
System.out.println("[MyInstantiationAwareBeanPostProcessor] before instantiation " + beanName);
return null;
}
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
System.out.println("[MyInstantiationAwareBeanPostProcessor] after instantiation " + beanName);
return true;
}
@Override
public PropertyValues postProcessPropertyValues(PropertyValues pvs, PropertyDescriptor[] pds, Object bean, String beanName) throws BeansException {
System.out.println("[MyInstantiationAwareBeanPostProcessor] postProcessPropertyValues " + beanName);
return pvs;
}
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
System.out.println("[MyInstantiationAwareBeanPostProcessor] before initialization " + beanName);
return bean;
}
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
System.out.println("[MyInstantiationAwareBeanPostProcessor] after initialization " + beanName);
return bean;
}
}7. SmartInstantiationAwareBeanPostProcessor
org.springframework.beans.factory.config.SmartInstantiationAwareBeanPostProcessor
Provides three extra hooks: predictBeanType , determineCandidateConstructors , and getEarlyBeanReference , allowing fine‑grained control over bean type prediction, constructor selection, and early reference exposure for circular dependencies.
public class MySmartInstantiationAwareBeanPostProcessor implements SmartInstantiationAwareBeanPostProcessor {
@Override
public Class
predictBeanType(Class
beanClass, String beanName) throws BeansException {
System.out.println("[MySmart...] predictBeanType " + beanName);
return beanClass;
}
@Override
public Constructor
[] determineCandidateConstructors(Class
beanClass, String beanName) throws BeansException {
System.out.println("[MySmart...] determineCandidateConstructors " + beanName);
return null;
}
@Override
public Object getEarlyBeanReference(Object bean, String beanName) throws BeansException {
System.out.println("[MySmart...] getEarlyBeanReference " + beanName);
return bean;
}
}8. BeanFactoryAware
org.springframework.beans.factory.BeanFactoryAware
Allows a bean to obtain a reference to the owning BeanFactory after instantiation but before property injection.
public class MyBeanFactoryAware implements BeanFactoryAware {
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
System.out.println("[MyBeanFactoryAware] " + beanFactory.getBean(MyBeanFactoryAware.class).getClass().getSimpleName());
}
}9. ApplicationContextAwareProcessor
org.springframework.context.support.ApplicationContextAwareProcessor
Although it does not define its own extension point, it internally triggers six Aware interfaces (EnvironmentAware, EmbeddedValueResolverAware, ResourceLoaderAware, ApplicationEventPublisherAware, MessageSourceAware, ApplicationContextAware) after bean instantiation and before initialization.
EnvironmentAware – access environment properties.
EmbeddedValueResolverAware – resolve ${…} placeholders.
ResourceLoaderAware – load resources from the classpath.
ApplicationEventPublisherAware – publish application events.
MessageSourceAware – obtain internationalization messages.
ApplicationContextAware – obtain the full ApplicationContext for bean lookup.
10. BeanNameAware
org.springframework.beans.factory.BeanNameAware
Provides the bean name before initialization, enabling custom naming logic.
public class MyBeanNameAware implements BeanNameAware {
@Override
public void setBeanName(String name) {
System.out.println("[BeanNameAware] " + name);
}
}11. @PostConstruct
javax.annotation.PostConstruct
Marks a method to be invoked after dependency injection but before any InitializingBean callbacks.
public class MyBean {
@PostConstruct
public void init() {
System.out.println("[PostConstruct] MyBean");
}
}12. InitializingBean
org.springframework.beans.factory.InitializingBean
Provides a single afterPropertiesSet method invoked after property injection and before the bean is made available.
public class MyInitializingBean implements InitializingBean {
@Override
public void afterPropertiesSet() throws Exception {
System.out.println("[InitializingBean] MyBean");
}
}13. FactoryBean
org.springframework.beans.factory.FactoryBean
Allows custom creation logic for complex beans; Spring itself provides dozens of implementations.
public class MyFactoryBean implements FactoryBean<MyFactoryBean.InnerBean> {
@Override
public MyFactoryBean.InnerBean getObject() throws Exception {
System.out.println("[FactoryBean] getObject");
return new InnerBean();
}
@Override
public Class<?> getObjectType() { return InnerBean.class; }
@Override
public boolean isSingleton() { return true; }
public static class InnerBean {}
}14. SmartInitializingSingleton
org.springframework.beans.factory.SmartInitializingSingleton
Callback invoked after all non‑lazy singleton beans have been instantiated.
public class MySmartInitializingSingleton implements SmartInitializingSingleton {
@Override
public void afterSingletonsInstantiated() {
System.out.println("[SmartInitializingSingleton]");
}
}15. CommandLineRunner
org.springframework.boot.CommandLineRunner
Runs after the Spring Boot application has started; multiple runners can be ordered with @Order .
public class MyCommandLineRunner implements CommandLineRunner {
@Override
public void run(String... args) throws Exception {
System.out.println("[CommandLineRunner]");
}
}16. DisposableBean
org.springframework.beans.factory.DisposableBean
Provides a destroy method called when the bean is being destroyed, e.g., during context shutdown.
public class MyDisposableBean implements DisposableBean {
@Override
public void destroy() throws Exception {
System.out.println("[DisposableBean] destroy");
}
}17. ApplicationListener
org.springframework.context.ApplicationListener
Listens to Spring events such as ContextRefreshedEvent , ContextStartedEvent , ContextStoppedEvent , ContextClosedEvent , and RequestHandledEvent , allowing custom behavior at various lifecycle stages.
18. Conclusion
The article summarizes the major Spring & Spring Boot extension points, illustrating how developers can hook into different phases of bean creation and container startup to implement custom initialization, resource loading, and cleanup logic. The next article will discuss controlling bean loading order in Spring Boot.
IT Xianyu
We share common IT technologies (Java, Web, SQL, etc.) and practical applications of emerging software development techniques. New articles are posted daily. Follow IT Xianyu to stay ahead in tech. The IT Xianyu series is being regularly updated.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.