<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>SpringBoot on 小蜜蜂</title>
        <link>https://xumf.net/tags/springboot/</link>
        <description>Recent content in SpringBoot on 小蜜蜂</description>
        <generator>Hugo -- gohugo.io</generator>
        <language>zh</language>
        <lastBuildDate>Tue, 09 May 2023 23:36:22 +0800</lastBuildDate><atom:link href="https://xumf.net/tags/springboot/index.xml" rel="self" type="application/rss+xml" /><item>
            <title>SpringBoot 启动流程</title>
            <link>https://xumf.net/blog/springbootstartflow/</link>
            <pubDate>Tue, 09 May 2023 23:36:22 +0800</pubDate>
            <guid>https://xumf.net/blog/springbootstartflow/</guid>
            <description>&lt;p&gt;Spring Boot 的启动入口是 &lt;code&gt;SpringApplication.run()&lt;/code&gt;，其核心流程可概括为三个阶段：&lt;strong&gt;准备阶段 → 刷新上下文 → 启动完成后的回调&lt;/strong&gt;。&lt;/p&gt;&#xA;&lt;h2 id=&#34;一整体启动流程&#34;&gt;一、整体启动流程&#xA;&lt;/h2&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-plain&#34; data-lang=&#34;plain&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;1. SpringApplication.run() 入口&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;2. 准备阶段：&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   ├─ 推断应用类型（Reactive / Servlet）&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   ├─ 加载所有 SpringApplicationRunListener&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   ├─ 构建并准备 Environment（解析 application.yml/properties）&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   └─ 打印 Banner&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;3. 创建并准备 ApplicationContext：&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   ├─ 创建上下文实例（AnnotationConfigServletWebServerApplicationContext）&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   ├─ 执行 ApplicationContextInitializer&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   ├─ 注册启动参数中的主配置类（@SpringBootApplication 标注的类）&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   └─ 调用 refresh() 方法 → 进入 Spring 容器核心流程&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;4. 刷新后回调：&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   ├─ 执行 CommandLineRunner / ApplicationRunner&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;   └─ 启动内嵌 Web 容器（Tomcat / Jetty / Undertow）&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;refresh()&lt;/code&gt; 方法是 Spring 容器初始化的核心，由 &lt;code&gt;AbstractApplicationContext.refresh()&lt;/code&gt; 定义，其中 13 个步骤依次执行。&lt;/p&gt;&#xA;&lt;h2 id=&#34;二refresh-核心步骤&#34;&gt;二、refresh() 核心步骤&#xA;&lt;/h2&gt;&lt;p&gt;&lt;code&gt;refresh()&lt;/code&gt; 中的关键步骤（按顺序）：&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;&lt;strong&gt;prepareRefresh()&lt;/strong&gt;：设置容器状态，初始化属性源和早期事件发布器&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;obtainFreshBeanFactory()&lt;/strong&gt;：刷新 BeanFactory，解析 Bean 定义（从配置类、XML、@ComponentScan 扫描结果）&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;prepareBeanFactory()&lt;/strong&gt;：配置 BeanFactory 的类加载器、SpEL 解析器、属性编辑器，注册 Aware 接口回调需要的 Bean&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;postProcessBeanFactory()&lt;/strong&gt;：子类扩展点（Web 容器在此注册 ServletContextAware 处理器）&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;invokeBeanFactoryPostProcessors()&lt;/strong&gt;：调用所有 BeanFactoryPostProcessor。最关键的是 &lt;strong&gt;ConfigurationClassPostProcessor&lt;/strong&gt;，它解析 @Configuration、@ComponentScan、@Import、@Bean 并注册所有 Bean 定义&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;registerBeanPostProcessors()&lt;/strong&gt;：注册 BeanPostProcessor。此时只注册不执行——真正执行时机在 bean 实例化阶段触发&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;initMessageSource()&lt;/strong&gt;：初始化国际化组件&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;initApplicationEventMulticaster()&lt;/strong&gt;：初始化事件广播器&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;onRefresh()&lt;/strong&gt;：创建并启动内嵌 Web 容器（Tomcat 在此启动）&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;registerListeners()&lt;/strong&gt;：注册所有的 ApplicationListener&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;finishBeanFactoryInitialization()&lt;/strong&gt;：实例化所有非懒加载的单例 Bean——这是&lt;strong&gt;启动最耗时&lt;/strong&gt;的阶段&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;finishRefresh()&lt;/strong&gt;：发布 ContextRefreshedEvent 事件&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h2 id=&#34;三核心-beanpostprocessor-详解&#34;&gt;三、核心 BeanPostProcessor 详解&#xA;&lt;/h2&gt;&lt;p&gt;BeanPostProcessor 在 bean 实例化过程的两个时机触发：&lt;strong&gt;初始化前（BeforeInitialization）&lt;/strong&gt; 和 &lt;strong&gt;初始化后（AfterInitialization）&lt;/strong&gt;。下面列出 Spring Boot 自动装配中最常用的几个：&lt;/p&gt;&#xA;&lt;h3 id=&#34;依赖注入相关&#34;&gt;依赖注入相关&#xA;&lt;/h3&gt;&lt;ol&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;AutowiredAnnotationBeanPostProcessor&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;处理 @Autowired、@Value、@Inject&lt;/li&gt;&#xA;&lt;li&gt;postProcessBeforeInitialization：解析注入点并注入依赖&lt;/li&gt;&#xA;&lt;li&gt;源码：&lt;code&gt;org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;CommonAnnotationBeanPostProcessor&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;处理 JSR-250 注解：@Resource、@PostConstruct、@PreDestroy&lt;/li&gt;&#xA;&lt;li&gt;@Resource 按名称优先注入，与 @Autowired 的 Type 优先策略不同——混用时注意&lt;/li&gt;&#xA;&lt;li&gt;源码：&lt;code&gt;org.springframework.context.annotation.CommonAnnotationBeanPostProcessor&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h3 id=&#34;生命周期回调相关&#34;&gt;生命周期回调相关&#xA;&lt;/h3&gt;&lt;ol start=&#34;3&#34;&gt;&#xA;&lt;li&gt;&lt;strong&gt;InitDestroyAnnotationBeanPostProcessor&lt;/strong&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;处理 @PostConstruct 和 @PreDestroy&lt;/li&gt;&#xA;&lt;li&gt;与 CommonAnnotationBeanPostProcessor 的职责有重叠——InitDestroyAnnotationBeanPostProcessor 更底层，CommonAnnotationBeanPostProcessor 扩展了对 @Resource 的支持&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h3 id=&#34;aware-接口注入&#34;&gt;Aware 接口注入&#xA;&lt;/h3&gt;&lt;ol start=&#34;4&#34;&gt;&#xA;&lt;li&gt;&lt;strong&gt;ApplicationContextAwareProcessor&lt;/strong&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;处理 ApplicationContextAware、EnvironmentAware、ResourceLoaderAware 等&lt;/li&gt;&#xA;&lt;li&gt;postProcessBeforeInitialization 阶段注入，早于 @Autowired&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h3 id=&#34;占位符解析&#34;&gt;占位符解析&#xA;&lt;/h3&gt;&lt;ol start=&#34;5&#34;&gt;&#xA;&lt;li&gt;&lt;strong&gt;EmbeddedValueResolverAwareBeanPostProcessor&lt;/strong&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;处理 EmbeddedValueResolverAware 接口，注入 StringValueResolver&lt;/li&gt;&#xA;&lt;li&gt;用于解析 &lt;code&gt;${property}&lt;/code&gt; 占位符和 &lt;code&gt;#{spEL}&lt;/code&gt; 表达式&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h3 id=&#34;aop-代理&#34;&gt;AOP 代理&#xA;&lt;/h3&gt;&lt;ol start=&#34;6&#34;&gt;&#xA;&lt;li&gt;&lt;strong&gt;InfrastructureAdvisorAutoProxyCreator&lt;/strong&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;为符合条件的 Bean 生成 AOP 代理&lt;/li&gt;&#xA;&lt;li&gt;postProcessAfterInitialization 阶段触发：先有 Bean 实例，再通过代理增加切面逻辑&lt;/li&gt;&#xA;&lt;li&gt;源码：&lt;code&gt;org.springframework.aop.framework.autoproxy. InfrastructureAdvisorAutoProxyCreator&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h3 id=&#34;异常转换&#34;&gt;异常转换&#xA;&lt;/h3&gt;&lt;ol start=&#34;7&#34;&gt;&#xA;&lt;li&gt;&lt;strong&gt;PersistenceExceptionTranslationPostProcessor&lt;/strong&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;将持久化层异常（JPA、Hibernate）转换为 Spring DataAccessException&lt;/li&gt;&#xA;&lt;li&gt;通常提前注册 BeanPostProcessor 以处理所有持久化 Bean&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h3 id=&#34;事件与注解驱动&#34;&gt;事件与注解驱动&#xA;&lt;/h3&gt;&lt;ol start=&#34;8&#34;&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;EventListenerMethodProcessor&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;处理 @EventListener，注册事件监听方法&lt;/li&gt;&#xA;&lt;li&gt;源码：&lt;code&gt;org.springframework.context.event.EventListenerMethodProcessor&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&#xA;&lt;p&gt;&lt;strong&gt;ScheduledAnnotationBeanPostProcessor&lt;/strong&gt;&lt;/p&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;处理 @Scheduled，注册定时任务&lt;/li&gt;&#xA;&lt;li&gt;与 @Async 由不同处理器管理：@Async 由 AsyncAnnotationBeanPostProcessor 处理&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h3 id=&#34;import-扩展&#34;&gt;Import 扩展&#xA;&lt;/h3&gt;&lt;ol start=&#34;10&#34;&gt;&#xA;&lt;li&gt;&lt;strong&gt;ImportAwareBeanPostProcessor&lt;/strong&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;处理 @Import 导入的类中实现 ImportAware 接口的 Bean&lt;/li&gt;&#xA;&lt;li&gt;postProcessBeforeInitialization 阶段注入导入元数据&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h2 id=&#34;四beanfactorypostprocessor&#34;&gt;四、BeanFactoryPostProcessor&#xA;&lt;/h2&gt;&lt;ol&gt;&#xA;&lt;li&gt;&lt;strong&gt;ConfigurationClassPostProcessor&lt;/strong&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;strong&gt;最重要的 BeanFactoryPostProcessor&lt;/strong&gt;，负责解析 @Configuration 类&lt;/li&gt;&#xA;&lt;li&gt;处理 @ComponentScan（包扫描）、@Import（导入配置类）、@Bean（方法级别 Bean 定义）&lt;/li&gt;&#xA;&lt;li&gt;在 invokeBeanFactoryPostProcessors() 阶段执行——比任何 BeanPostProcessor 都早&lt;/li&gt;&#xA;&lt;li&gt;没有它，所有注解配置的 Bean 都不会被注册&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h2 id=&#34;五常见问题排查&#34;&gt;五、常见问题排查&#xA;&lt;/h2&gt;&lt;ol&gt;&#xA;&lt;li&gt;&lt;strong&gt;启动慢怎么办？&lt;/strong&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;排查点：finishBeanFactoryInitialization 阶段耗时最长，检查是否有大量懒加载泄漏、@ComponentScan 覆盖过多包路径&lt;/li&gt;&#xA;&lt;li&gt;启用 lazy-initialization（&lt;code&gt;spring.main.lazy-initialization=true&lt;/code&gt;）可加速启动，但注意首次请求变慢&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;Bean 初始化异常如何排查？&lt;/strong&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;开启 &lt;code&gt;debug=true&lt;/code&gt; 查看 ConditionEvaluationReport（自动配置条件评估报告）&lt;/li&gt;&#xA;&lt;li&gt;关键日志关键词：&lt;code&gt;UnsatisfiedDependencyException&lt;/code&gt;、&lt;code&gt;BeanCreationException&lt;/code&gt;、&lt;code&gt;NoSuchBeanDefinitionException&lt;/code&gt;&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;AOP 代理不生效？&lt;/strong&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;检查类是否被 final 修饰（CGLIB 无法代理 final 类）&lt;/li&gt;&#xA;&lt;li&gt;检查同一个类内部方法调用 AOP 代理问题（自调用不走代理）&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;@PostConstruct 与 afterPropertiesSet 的执行顺序？&lt;/strong&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;&lt;code&gt;InitializingBean.afterPropertiesSet()&lt;/code&gt; → &lt;code&gt;@PostConstruct&lt;/code&gt; → 自定义 &lt;code&gt;init-method&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;顺序：InitializingBean → BeanPostProcessor.postProcessBeforeInitialization → @PostConstruct → afterPropertiesSet → init-method → BeanPostProcessor.postProcessAfterInitialization&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;li&gt;&lt;strong&gt;ConfigurationClassPostProcessor 的常见错误&lt;/strong&gt;&#xA;&lt;ul&gt;&#xA;&lt;li&gt;@ComponentScan 未生效：检查启动类的位置是否在根包&lt;/li&gt;&#xA;&lt;li&gt;@Bean 方法被 final 修饰：CGLIB 无法重写 final 方法&lt;/li&gt;&#xA;&lt;li&gt;@Import 导入的配置类重复：Spring 5.2+ 支持 @Import 去重，但注意 @Import 和 @ComponentScan 同时扫描到同一个类会导致重复注册&lt;/li&gt;&#xA;&lt;/ul&gt;&#xA;&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;</description>
        </item></channel>
</rss>
