Spring Boot 的核心优势之一是**“约定大于配置”**,但在实际开发中,我们往往需要基于业务场景定制化扩展框架行为。这些可扩展的入口被称为“扩展点”,它们分布在 Spring Boot 启动、Bean 生命周期、Web 处理、配置加载等核心流程中。
本文将通过流程图解 + 扩展点定位 + 用法示例,系统梳理 Spring Boot 所有核心扩展点,帮助你精准掌握框架定制化的关键入口。
一、先理清核心脉络:Spring Boot 启动流程
理解扩展点的前提是掌握 Spring Boot 启动的核心流程,所有扩展点都依附于这个流程的关键节点:
【启动入口】
↓
SpringApplication.run()
↓
1. 初始化 SpringApplication(加载初始化器、监听器)
↓
2. 启动 Spring 上下文(ConfigurableApplicationContext)
↓
├─ 环境准备(Environment 加载配置)
├─ 上下文初始化(执行初始化器)
├─ 刷新上下文(核心:BeanFactory 初始化、Bean 生命周期)
└─ 启动完成(发布启动事件)
↓
3. 运行回调(CommandLineRunner/ApplicationRunner)
↓
【应用就绪】
以下所有扩展点都将对应到这个流程的具体节点,先看整体扩展点分布总图:
┌─────────────────────────────────────────────────────────────┐
│ Spring Boot 扩展点全景 │
├───────────────────┬─────────────────────────────────────────┤
│ 扩展阶段 │ 核心扩展点 │
├───────────────────┼─────────────────────────────────────────┤
│ 应用启动初始化 │ ApplicationContextInitializer │
│ │ ApplicationListener/ApplicationEvent │
├───────────────────┼─────────────────────────────────────────┤
│ 配置加载 │ EnvironmentPostProcessor │
│ │ PropertySourceLocator │
│ │ @ConfigurationProperties │
│ │ PropertyEditor/Converter │
├───────────────────┼─────────────────────────────────────────┤
│ Bean 生命周期 │ BeanDefinitionRegistryPostProcessor │
│ │ BeanFactoryPostProcessor │
│ │ BeanPostProcessor │
│ │ InitializingBean/DisposableBean │
│ │ @PostConstruct/@PreDestroy │
├───────────────────┼─────────────────────────────────────────┤
│ 应用启动完成 │ CommandLineRunner/ApplicationRunner │
├───────────────────┼─────────────────────────────────────────┤
│ Web 专属扩展 │ WebMvcConfigurer/WebFluxConfigurer │
│ │ HandlerInterceptor │
│ │ Filter/Interceptor │
│ │ ErrorController │
├───────────────────┼─────────────────────────────────────────┤
│ 容器扩展 │ Customizer(如 RestTemplateCustomizer) │
│ │ Condition(@Conditional) │
│ │ FactoryBean │
├───────────────────┼─────────────────────────────────────────┤
│ 应用关闭 │ ApplicationListener<ContextClosedEvent> │
│ │ DisposableBean/@PreDestroy │
│ │ ShutdownHook │
└───────────────────┴─────────────────────────────────────────┘
二、分阶段详解扩展点(附图解+示例)
阶段1:应用启动初始化(SpringApplication 初始化)
对应流程:SpringApplication 实例创建 → 上下文初始化前
核心扩展点作用:在上下文初始化前定制环境、上下文配置。
1. ApplicationContextInitializer
- 定位:Spring 上下文初始化前执行,用于定制 ConfigurableApplicationContext。
- 触发时机:SpringApplication 初始化后,上下文刷新前。
- 图解节点:
SpringApplication.run() ↓ 创建 ApplicationContext ↓ 执行 ApplicationContextInitializer(可多个,按Order排序) ↓ 刷新上下文 - 示例:
@Order(1) public class CustomApplicationContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> { @Override public void initialize(ConfigurableApplicationContext applicationContext) { // 定制上下文:比如添加自定义 PropertySource ConfigurableEnvironment environment = applicationContext.getEnvironment(); environment.getPropertySources().addFirst(new MapPropertySource("custom", Map.of("custom.key", "custom.value"))); } } // 注册方式1:META-INF/spring.factories // org.springframework.context.ApplicationContextInitializer=com.example.CustomApplicationContextInitializer // 注册方式2:SpringApplication.addInitializers()
2. ApplicationListener(事件监听)
- 定位:监听 Spring Boot 生命周期事件(如启动、刷新、关闭),实现事件驱动扩展。
- 核心事件:
事件类型 触发时机 ApplicationStartingEvent 应用刚启动,上下文未创建 ApplicationEnvironmentPreparedEvent 环境准备完成 ApplicationContextInitializedEvent 上下文初始化完成 ApplicationStartedEvent 上下文刷新完成,Runner未执行 ApplicationReadyEvent 应用就绪,可处理请求 ContextClosedEvent 应用关闭 - 图解:
ApplicationStartingEvent → ApplicationEnvironmentPreparedEvent → ApplicationContextInitializedEvent → ApplicationStartedEvent → ApplicationReadyEvent - 示例:
@Component public class CustomApplicationListener implements ApplicationListener<ApplicationReadyEvent> { @Override public void onApplicationEvent(ApplicationReadyEvent event) { // 应用就绪后执行:比如打印启动完成日志、初始化缓存 System.out.println("应用启动完成,端口:" + event.getApplicationContext().getEnvironment().getProperty("server.port")); } }
阶段2:配置加载扩展(Environment 定制)
对应流程:环境(Environment)初始化 → 配置属性加载
核心扩展点作用:定制配置加载来源、属性转换、配置绑定。
1. EnvironmentPostProcessor
- 定位:在 Environment 准备完成后,进一步定制环境(比 ApplicationContextInitializer 更早干预配置)。
- 图解:
SpringApplication.run() → 初始化 Environment → 执行 EnvironmentPostProcessor → 加载 application.yml/properties - 示例:加载自定义配置文件
public class CustomEnvironmentPostProcessor implements EnvironmentPostProcessor { @Override public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) { // 加载自定义配置文件:比如 config/custom.yml Resource resource = new ClassPathResource("config/custom.yml"); if (resource.exists()) { try { YamlPropertySourceLoader loader = new YamlPropertySourceLoader(); PropertySource<?> propertySource = loader.load("customConfig", resource).get(0); environment.getPropertySources().addAfter("applicationConfig: [classpath:/application.yml]", propertySource); } catch (IOException e) { throw new RuntimeException(e); } } } // 注册:META-INF/spring.factories // org.springframework.boot.env.EnvironmentPostProcessor=com.example.CustomEnvironmentPostProcessor }
2. PropertySourceLocator
- 定位:自定义配置来源(比如从 Nacos/Apollo 加载配置),是 Spring Cloud 配置中心的核心扩展点。
- 示例:
public class CustomPropertySourceLocator implements PropertySourceLocator { @Override public PropertySource<?> locate(Environment environment) { // 从自定义来源(如数据库)加载配置 Map<String, Object> configMap = new HashMap<>(); configMap.put("db.url", "jdbc:mysql://localhost:3306/test"); return new MapPropertySource("dbConfig", configMap); } } // 注册:通过 EnvironmentPostProcessor 添加
3. @ConfigurationProperties + PropertyEditor/Converter
- 定位:配置属性绑定 + 自定义类型转换(比如 String → 自定义对象)。
- 示例:
// 配置绑定 @ConfigurationProperties(prefix = "custom.db") @Component public class DbProperties { private String url; private String username; // getter/setter } // 自定义类型转换器 @Component public class StringToDateConverter implements Converter<String, LocalDate> { @Override public LocalDate convert(String source) { return LocalDate.parse(source, DateTimeFormatter.ofPattern("yyyy-MM-dd")); } }
阶段3:Bean 生命周期扩展(核心)
对应流程:BeanDefinition 注册 → BeanFactory 初始化 → Bean 实例化/初始化/销毁
这是 Spring 最核心的扩展区域,所有 Bean 相关定制都在这里。
核心流程图解(Bean 生命周期):
1. 扫描 BeanDefinition → 注册到 BeanDefinitionRegistry
↓
2. 执行 BeanDefinitionRegistryPostProcessor(修改 BeanDefinition)
↓
3. 执行 BeanFactoryPostProcessor(定制 BeanFactory)
↓
4. Bean 实例化(newInstance)
↓
5. 依赖注入(populateBean)
↓
6. 执行 BeanPostProcessor.postProcessBeforeInitialization
↓
7. Bean 初始化:
├─ @PostConstruct
├─ InitializingBean.afterPropertiesSet()
└─ 自定义 init-method
↓
8. 执行 BeanPostProcessor.postProcessAfterInitialization
↓
9. Bean 就绪使用
↓
10. 容器关闭:
├─ @PreDestroy
├─ DisposableBean.destroy()
└─ 自定义 destroy-method
关键扩展点详解:
1. BeanDefinitionRegistryPostProcessor
- 定位:BeanDefinition 注册完成后,可新增/修改/删除 BeanDefinition(优先级高于 BeanFactoryPostProcessor)。
- 示例:动态注册 Bean
@Component public class CustomBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor { @Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { // 动态注册一个 BeanDefinition RootBeanDefinition beanDefinition = new RootBeanDefinition(CustomService.class); registry.registerBeanDefinition("customService", beanDefinition); } @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { // 可选:后续处理 BeanFactory } }
2. BeanFactoryPostProcessor
- 定位:BeanFactory 初始化完成后,Bean 实例化前,定制 BeanFactory(比如修改 Bean 属性)。
- 示例:
@Component public class CustomBeanFactoryPostProcessor implements BeanFactoryPostProcessor { @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { // 修改已注册的 BeanDefinition 属性 BeanDefinition beanDefinition = beanFactory.getBeanDefinition("userService"); beanDefinition.getPropertyValues().add("username", "admin"); } }
3. BeanPostProcessor
- 定位:Bean 实例化后、初始化前后执行,是最常用的扩展点(比如 AOP 代理、属性修改)。
- 示例:
@Component public class CustomBeanPostProcessor implements BeanPostProcessor { // 初始化前执行 @Override public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException { if (bean instanceof UserService) { System.out.println("UserService 初始化前:" + beanName); } return bean; } // 初始化后执行(比如生成代理对象) @Override public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { if (bean instanceof UserService) { System.out.println("UserService 初始化后:" + beanName); } return bean; } }
4. InitializingBean / @PostConstruct / init-method
- 定位:Bean 初始化阶段执行(优先级:@PostConstruct > InitializingBean > init-method)。
- 示例:
@Component public class UserService implements InitializingBean { // 1. @PostConstruct 最先执行 @PostConstruct public void postConstruct() { System.out.println("PostConstruct 执行"); } // 2. InitializingBean 其次 @Override public void afterPropertiesSet() throws Exception { System.out.println("afterPropertiesSet 执行"); } // 3. init-method 最后(需配置) public void initMethod() { System.out.println("init-method 执行"); } } // 配置 init-method(可选) @Bean(initMethod = "initMethod") public UserService userService() { return new UserService(); }
阶段4:应用启动完成扩展
对应流程:上下文刷新完成 → 应用就绪
核心扩展点:CommandLineRunner / ApplicationRunner(启动后执行任务)。
图解:
ApplicationContext 刷新完成 → 执行 ApplicationRunner(按Order) → 执行 CommandLineRunner(按Order) → ApplicationReadyEvent
示例:
// ApplicationRunner(接收解析后的参数)
@Component
@Order(1)
public class CustomApplicationRunner implements ApplicationRunner {
@Override
public void run(ApplicationArguments args) throws Exception {
System.out.println("ApplicationRunner 执行,参数:" + args.getOptionNames());
}
}
// CommandLineRunner(接收原始命令行参数)
@Component
@Order(2)
public class CustomCommandLineRunner implements CommandLineRunner {
@Override
public void run(String... args) throws Exception {
System.out.println("CommandLineRunner 执行,参数:" + Arrays.toString(args));
}
}
阶段5:Web 专属扩展(Spring MVC/WebFlux)
如果是 Web 应用,新增以下扩展点:
1. WebMvcConfigurer(MVC 定制)
- 定位:定制 Spring MVC 配置(拦截器、视图解析器、消息转换器等)。
- 示例:
@Configuration public class CustomWebMvcConfigurer implements WebMvcConfigurer { // 添加拦截器 @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(new CustomHandlerInterceptor()).addPathPatterns("/**"); } // 定制消息转换器(比如 FastJSON) @Override public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter(); converters.add(converter); } }
2. HandlerInterceptor(请求拦截)
- 定位:拦截 HTTP 请求(预处理、后处理、完成后)。
- 示例:
public class CustomHandlerInterceptor implements HandlerInterceptor { @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { // 请求处理前执行(返回false则拦截) System.out.println("preHandle:" + request.getRequestURI()); return true; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { // 请求处理后,视图渲染前 } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { // 视图渲染后(无论是否异常) } }
3. ErrorController(全局异常页面/JSON)
- 定位:定制错误页面/错误 JSON 响应。
- 示例:
@RestController public class CustomErrorController implements ErrorController { @RequestMapping("/error") public Map<String, Object> handleError(HttpServletRequest request) { Map<String, Object> error = new HashMap<>(); error.put("code", request.getAttribute("javax.servlet.error.status_code")); error.put("message", request.getAttribute("javax.servlet.error.message")); return error; } // Spring Boot 2.3+ 推荐用 ErrorAttributes 替代 @Component public static class CustomErrorAttributes extends DefaultErrorAttributes { @Override public Map<String, Object> getErrorAttributes(WebRequest webRequest, ErrorAttributeOptions options) { Map<String, Object> attrs = super.getErrorAttributes(webRequest, options); attrs.put("custom", "自定义错误信息"); return attrs; } } }
阶段6:其他核心扩展点
1. Customizer 定制器
- 定位:框架提供的标准化定制接口(比如 RestTemplateCustomizer、Jackson2ObjectMapperBuilderCustomizer)。
- 示例:定制 RestTemplate
@Component public class CustomRestTemplateCustomizer implements RestTemplateCustomizer { @Override public void customize(RestTemplate restTemplate) { // 添加拦截器、设置超时时间等 restTemplate.setRequestFactory(new HttpComponentsClientHttpRequestFactory()); restTemplate.getInterceptors().add(new CustomClientHttpRequestInterceptor()); } }
2. @Conditional(条件装配)
- 定位:根据条件动态装配 Bean(比如不同环境加载不同 Bean)。
- 常用条件注解:
@ConditionalOnClass:类存在时装配@ConditionalOnMissingClass:类不存在时装配@ConditionalOnBean:Bean 存在时装配@ConditionalOnProperty:配置属性满足时装配
- 示例:
@Bean @ConditionalOnProperty(prefix = "feature", name = "redis.enabled", havingValue = "true") public RedisTemplate<String, Object> redisTemplate() { return new RedisTemplate<>(); }
3. FactoryBean
- 定位:定制 Bean 的实例化过程(比如创建复杂对象、代理对象)。
- 示例:
@Component public class CustomFactoryBean implements FactoryBean<CustomObject> { // 创建 Bean 实例 @Override public CustomObject getObject() throws Exception { CustomObject obj = new CustomObject(); obj.setId(1); obj.setName("FactoryBean 创建"); return obj; } // 指定 Bean 类型 @Override public Class<?> getObjectType() { return CustomObject.class; } }
阶段7:应用关闭扩展
对应流程:容器关闭 → Bean 销毁
核心扩展点:
ApplicationListener<ContextClosedEvent>:监听容器关闭事件;DisposableBean/@PreDestroy/destroy-method:Bean 销毁阶段执行;ShutdownHook:JVM 关闭钩子(Spring Boot 已默认注册,可自定义)。
三、扩展点优先级总结
为了方便记忆,整理核心扩展点的执行优先级(从早到晚):
1. ApplicationStartingEvent(监听器)
2. EnvironmentPostProcessor
3. ApplicationEnvironmentPreparedEvent(监听器)
4. ApplicationContextInitializer
5. ApplicationContextInitializedEvent(监听器)
6. BeanDefinitionRegistryPostProcessor
7. BeanFactoryPostProcessor
8. Bean 实例化 → BeanPostProcessor.postProcessBeforeInitialization
9. @PostConstruct → InitializingBean → init-method
10. BeanPostProcessor.postProcessAfterInitialization
11. ApplicationStartedEvent(监听器)
12. ApplicationRunner → CommandLineRunner
13. ApplicationReadyEvent(监听器)
14. 应用运行中(Web 拦截器/过滤器等)
15. ContextClosedEvent(监听器)→ @PreDestroy → DisposableBean → destroy-method
四、扩展点使用建议
- 优先使用框架标准化扩展点:比如 Customizer、WebMvcConfigurer,而非直接修改 BeanFactory;
- 利用 @Order 控制执行顺序:多个同类型扩展点通过
@Order或Ordered接口指定顺序; - 避免过度扩展:优先使用注解(如 @PostConstruct)而非底层扩展点(如 BeanPostProcessor);
- 注册方式:
- 轻量级扩展(如监听器、初始化器):通过
META-INF/spring.factories注册; - 业务相关扩展:通过
@Component或@Bean注册。
- 轻量级扩展(如监听器、初始化器):通过