前言
前面 10 篇,我们拆解了 IOC、Bean 生命周期、AOP、事务、SpringMVC、Boot 自动配置、环境配置、事件、类型转换。Spring 所有高阶能力、第三方框架整合(MyBatis、Feign、Dubbo),全部依赖 Spring 预留的扩展钩子。本章内容相对枯燥,到了从入门到放弃的阶段了 O(∩_∩)O。
接下来让我开始枯燥的旅程吧!!!
一、容器启动阶段扩展(Bean 还没创建)
1. BeanDefinitionRegistryPostProcessor
BeanDefinitionRegistryPostProcessor 继承了 BeanFactoryPostProcessor,因此它既是 BeanDefinitionRegistryPostProcessor 也是 BeanFactoryPostProcessor。Spring 容器的执行顺序如下:
- 首先执行所有实现了
PriorityOrdered接口的BeanDefinitionRegistryPostProcessor的postProcessBeanDefinitionRegistry()方法。 - 然后执行所有实现了
Ordered接口的。 - 接着执行其他所有的
BeanDefinitionRegistryPostProcessor。 - 之后,才会执行上述所有实现了
PriorityOrdered、Ordered以及其他BeanDefinitionRegistryPostProcessor的postProcessBeanFactory()方法(这是来自其父接口BeanFactoryPostProcessor的方法)。 - 最后,才轮到其他只实现了
BeanFactoryPostProcessor接口的普通后置处理器。
核心源码位置:
java
// PostProcessorRegistrationDelegate
invokeBeanFactoryPostProcessors(beanFactory);
核心能力:
- 拥有
BeanDefinitionRegistry能力 - 可以手动
registry.registerBeanDefinition() - 核心作用:动态扫描、动态注册 Bean 定义,不用写
@Component
经典落地案例:
- MyBatis:
MapperScannerConfigurer扫描 Mapper 接口 - Feign:批量注册 Feign 接口 BeanDefinition
代码示例:
java
@Component
public class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
// 这一步可以动态注册 BeanDefinition,例如:
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(MyService.class);
registry.registerBeanDefinition("myService", builder.getBeanDefinition());
}
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
// 这里的执行时机晚于 postProcessBeanDefinitionRegistry,但早于普通 BeanFactoryPostProcessor
// 注意:此时不能获取尚未完全初始化的 Bean 实例,仅能操作 BeanFactory。
}
}
典型框架落地案例:
MyBatis‑Spring 的 MapperScannerConfigurer 就是通过实现 BeanDefinitionRegistryPostProcessor,在 postProcessBeanDefinitionRegistry() 中扫描 Mapper 接口,并动态注册 MapperFactoryBean 的 BeanDefinition,从而实现无需手动配置每个 Mapper。
⚠️ 陷阱提醒:
如果同时需要实现 BeanDefinitionRegistryPostProcessor 和 BeanFactoryPostProcessor,建议直接实现前者(因为已继承后者),并务必实现 postProcessBeanDefinitionRegistry 方法,不要只重写 postProcessBeanFactory,否则无法执行注册阶段的逻辑。
2. BeanFactoryPostProcessor
执行时机: BeanDefinition 全部加载完成,Bean 还没有实例化
核心区别:
BeanFactoryPostProcessor的主要职责是修改已注册的 BeanDefinition(比如修改属性值、作用域等)。BeanDefinitionRegistryPostProcessor则专注于新增或动态注册 BeanDefinition。
经典落地:
ConfigurationClassPostProcessor 解析 @Configuration、@Bean、@Import、组件扫描是 Spring 全注解开发的核心底层。
区别口诀:
BeanDefinitionRegistryPostProcessor👉 注册 BeanBeanFactoryPostProcessor👉 修改 Bean 定义
二、Bean 生命周期级扩展(最核心、面试最重)
1. BeanPostProcessor
执行时机: Bean 实例化 + 属性填充完成后
两个关键方法:
postProcessBeforeInitialization:初始化方法之前,在 Bean 执行了@PostConstruct、afterPropertiesSet()以及自定义init-method之前调用。postProcessAfterInitialization:初始化方法之后,在以上所有初始化回调全部完成之后调用。
顺序控制: BeanPostProcessor 的排序依据是 PriorityOrdered 和 Ordered 接口,而不是 @Order 注解。@Order 注解主要影响的是组件在被注入到集合时的存储顺序,并不能用于定义 BeanPostProcessor 的执行优先级。
核心源码位置: AbstractAutowireCapableBeanFactory#initializeBean()
java
// 前置处理
wrappedBean = applyBeanPostProcessorsBeforeInitialization(wrappedBean, beanName);
// 初始化方法执行
invokeInitMethods(beanName, wrappedBean, mbd);
// 后置处理
wrappedBean = applyBeanPostProcessorsAfterInitialization(wrappedBean, beanName);
核心作用: 拦截所有 Bean,包装、替换、代理、增强。
经典落地:
- AOP 代理创建:
AnnotationAwareAspectJAutoProxyCreator - 依赖注入:
AutowiredAnnotationBeanPostProcessor处理@Autowired、@Value - 事务代理、动态代理全部依靠它
1.1 InstantiationAwareBeanPostProcessor 的隐藏陷阱
⚠️ 关键陷阱: 如果 postProcessAfterInstantiation 方法返回 false,Spring 会跳过对该 Bean 实例的属性填充(populateBean),并且后续的 InstantiationAwareBeanPostProcessor 实例也不会再被调用。但请注意,其他普通的 BeanPostProcessor(如用于 AOP 的代理创建)仍然会被正常执行。
示例代码:
java
@Component
public class MyInstantiationProcessor implements InstantiationAwareBeanPostProcessor {
@Override
public boolean postProcessAfterInstantiation(Object bean, String beanName) throws BeansException {
if (bean instanceof SomeSpecialBean) {
// 对于某种特殊 Bean,我们决定手动处理属性,跳过自动填充
return false;
}
return true; // 绝大多数情况应返回 true
}
}
1.2 BeanPostProcessor 注册的危险误区
🚨 非常容易出错的注册方式:
在 @Configuration 类中,如果使用非静态 @Bean 方法声明一个 BeanPostProcessor,Spring 会过早地创建它依赖的其他 Bean,从而破坏正常的 Bean 实例化顺序,导致容器启动失败或循环依赖。
正确做法:
- 将该
@Bean方法声明为static,或 - 将
BeanPostProcessor实现类直接用@Component注解并确保组件扫描路径包含它。
错误示例:
java
@Configuration
public class AppConfig {
@Bean // ❌ 非静态方法,会导致 MyBeanPostProcessor 依赖的 bean 被提前创建
public MyBeanPostProcessor myBeanPostProcessor() {
return new MyBeanPostProcessor();
}
}
如果用非静态方法注册它们:Spring 必须先实例化你的配置类 → 才能调用方法创建后置处理器但后置处理器是用来初始化配置类的 → 死循环 / 提前初始化 / 配置不生效
正确示例:
java
@Configuration
public class AppConfig {
@Bean
public static MyBeanPostProcessor myBeanPostProcessor() { // ✅ 静态方法
return new MyBeanPostProcessor();
}
}
2. InitializingBean + @PostConstruct + init-method
执行顺序: @PostConstruct → InitializingBean#afterPropertiesSet() → 自定义 init-method
源码位置: AbstractAutowireCapableBeanFactory#invokeInitMethods
作用: 单个 Bean 初始化业务逻辑,无全局影响。
3. DisposableBean + destroy-method
执行时机: 容器关闭、单例 Bean 销毁
源码位置: DefaultSingletonBeanRegistry#destroySingletons()
4. FactoryBean
底层接口:
java
public interface FactoryBean<T> {
T getObject() throws Exception;
Class<?> getObjectType();
}
作用: 用来构建复杂、重对象,屏蔽复杂创建逻辑。容器最终存的是 getObject() 返回的对象。
经典落地:
- MyBatis:
SqlSessionFactoryBean - 连接池、中间件复杂 Bean 构建
三、注解驱动扩展(自动配置核心)
1. ImportSelector
执行时机: 解析 @Import 时执行
分类:
- 普通
ImportSelector DeferredImportSelector延迟导入(所有配置类解析完再执行)
核心落地: SpringBoot 自动配置:AutoConfigurationImportSelector 加载所有自动配置类
2. ImportBeanDefinitionRegistrar
执行时机: 配置类解析阶段
作用: 手动编码批量注册 BeanDefinition,不限制注解、不限制扫描路径。
经典落地:
@MapperScan@EnableFeignClients- 所有
Enable开头的开关注解底层基本都靠它
四、事件 & 环境扩展
1. ApplicationListener / @EventListener
源码入口: AbstractApplicationContext#publishEvent()
作用: 容器刷新、启动、关闭、自定义业务事件解耦神器
2. EnvironmentPostProcessor
执行时机: SpringBoot 最早环境准备阶段
作用: 自定义加载配置文件、扩展配置源,对应第 8 篇 Environment 体系。
五、SpringMVC 专属扩展(Web 层)
对应第 6 篇 MVC 完整流程
- HandlerInterceptor :
preHandle/postHandle/afterCompletion - HandlerMethodArgumentResolver:自定义参数解析,实现自定义注解参数
- HandlerMethodReturnValueHandler:统一返回值封装、全局响应处理
- WebMvcConfigurer:跨域、拦截器、资源映射、消息转换器配置
六、全网必背:Spring 扩展点完整执行时序
- EnvironmentPostProcessor 👉 环境配置早期扩展
- BeanDefinitionRegistryPostProcessor 👉 动态注册 Bean
- BeanFactoryPostProcessor 👉 修改 BeanDefinition
- Bean 实例化 + 依赖填充
- BeanPostProcessor#Before
- @PostConstruct
- InitializingBean#afterPropertiesSet
- 自定义 init-method
- BeanPostProcessor#After 👉 AOP 代理、最终 Bean 成品
- 容器刷新完成:ContextRefreshedEvent
- 容器关闭:DisposableBean / destroy
七、场景选型(工作直接对照用)
| 需求场景 | 推荐扩展点 |
|---|---|
| 要动态造 Bean、扫接口、中间件整合 | ImportBeanDefinitionRegistrar / BeanDefinitionRegistryPostProcessor |
| 要修改全局 Bean 定义、动态配置 | BeanFactoryPostProcessor |
| 要给所有 Bean 做代理、增强、注入 | BeanPostProcessor |
| 复杂对象创建、组装 | FactoryBean |
| 自动配置、批量导入配置类 | DeferredImportSelector |
| 解耦、异步事件、业务解耦 | ApplicationListener |