网站建设服务器什么意思新密郑州网站建设
2025/12/31 14:22:12 网站建设 项目流程
网站建设服务器什么意思,新密郑州网站建设,广州冼村房价,莆田网站建设创意Spring Boot 启动流程源码解析#xff1a;从 main() 到 Web 服务就绪 一句 SpringApplication.run() 背后#xff0c;藏着整个 Spring 生态的启动引擎。 你是否曾#xff1a; 在面试被问#xff1a;“Spring Boot 启动过程做了哪些事#xff1f;”遇到启动慢、Bean 找不到…Spring Boot 启动流程源码解析从main()到 Web 服务就绪一句SpringApplication.run()背后藏着整个 Spring 生态的启动引擎。你是否曾在面试被问“Spring Boot 启动过程做了哪些事”遇到启动慢、Bean 找不到、配置不生效等问题却无从下手想自定义启动行为如动态加载配置、埋点监控但不知从何切入答案都在SpringApplication.run()的源码里。今天我们就逐行拆解 Spring Boot 3.x兼容 2.x的启动主流程带你从main()方法一路走到内嵌 Tomcat 启动完成一、入口main()方法SpringBootApplication public class MyApp { public static void main(String[] args) { SpringApplication.run(MyApp.class, args); } }看似简单实则调用了SpringApplication的静态方法// SpringApplication.java public static ConfigurableApplicationContext run(Class? primarySource, String... args) { return run(new Class?[] { primarySource }, args); } public static ConfigurableApplicationContext run(Class?[] primarySources, String[] args) { return new SpringApplication(primarySources).run(args); }✅关键点先构造SpringApplication实例再调用其run()方法。二、阶段 1构造SpringApplication对象public SpringApplication(ResourceLoader resourceLoader, Class?... primarySources) { this.resourceLoader resourceLoader; Assert.notNull(primarySources, PrimarySources must not be null); this.primarySources new LinkedHashSet(Arrays.asList(primarySources)); // 1. 推断应用类型SERVLET / REACTIVE / NONE this.properties.setWebApplicationType(WebApplicationType.deduceFromClasspath()); // 2. 从 spring.factories 加载 BootstrapRegistryInitializer this.bootstrapRegistryInitializers new ArrayList( getSpringFactoriesInstances(BootstrapRegistryInitializer.class)); // 3. 从 spring.factories 加载 ApplicationContextInitializer setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class)); // 4. 从 spring.factories 加载 ApplicationListener setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class)); // 5. 推断主配置类即包含 main 方法的类 this.mainApplicationClass deduceMainApplicationClass(); } 核心动作推断 Web 类型SERVLETclasspath 中存在 Spring MVC 相关类如 DispatcherServlet REACTIVE存在 WebFlux 相关类如 DispatcherHandler NONE非 Web 应用如批处理、定时任务加载扩展点通过SpringFactoriesLoader读取META-INF/spring.factories中的 SPI 实现。 这就是 Spring Boot自动装配和扩展机制的起点。三、阶段 2执行run(args)—— 启动主流程这是最核心的方法我们分步解析步骤 1准备监听器SpringApplicationRunListeners listeners getRunListeners(args); listeners.starting(bootstrapContext, this.mainApplicationClass);getRunListeners()返回所有SpringApplicationRunListener实例默认是EventPublishingRunListenerstarting()发布ApplicationStartingEvent→ 可用于早期日志初始化、APM 埋点步骤 2准备 Environment环境DefaultBootstrapContext bootstrapContext createBootstrapContext(); ConfigurableEnvironment environment prepareEnvironment(listeners, bootstrapContext, applicationArguments);在prepareEnvironment()中创建EnvironmentStandardServletEnvironment调用environmentPrepared()→ 发布ApplicationEnvironmentPreparedEvent此时application.properties已加载实战价值Nacos/Apollo 客户端在此阶段注入远程配置步骤 3创建 ApplicationContext应用上下文context createApplicationContext();根据webApplicationType选择上下文类型SERVLET→AnnotationConfigServletWebServerApplicationContextREACTIVE→AnnotationConfigReactiveWebServerApplicationContext该上下文继承自GenericApplicationContext并具备内嵌 Web 容器支持。步骤 4准备上下文prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);内部关键操作注册bannerBean应用所有ApplicationContextInitializer发布ApplicationContextInitializedEvent⚠️ 注意此时Bean 还未实例化只是定义已加载。步骤 5刷新上下文Refresh—— 最重量级阶段refreshContext(context);最终调用AbstractApplicationContext.refresh()Spring Framework 的核心方法Override public void refresh() throws BeansException, IllegalStateException { synchronized (this.startupShutdownMonitor) { // 1. 准备刷新记录启动时间、设置活跃状态 prepareRefresh(); // 2. 获取 BeanFactory通常是 DefaultListableBeanFactory ConfigurableListableBeanFactory beanFactory obtainFreshBeanFactory(); // 3. 配置 BeanFactory设置类加载器、表达式解析器等 prepareBeanFactory(beanFactory); // 4. 执行 BeanFactoryPostProcessor如 ConfigurationProperties 绑定 invokeBeanFactoryPostProcessors(beanFactory); // 5. 注册 BeanPostProcessor registerBeanPostProcessors(beanFactory); // 6. 初始化 MessageSource国际化 initMessageSource(); // 7. 初始化事件广播器 initApplicationEventMulticaster(); // 8. 【模板方法】子类可扩展如 ServletWebServerApplicationContext 会在此启动内嵌容器 onRefresh(); // 9. 注册监听器 registerListeners(); // 10. 实例化所有非懒加载的单例 Bean finishBeanFactoryInitialization(beanFactory); // 11. 完成刷新发布 ContextRefreshedEvent finishRefresh(); } } 重点子阶段解析invokeBeanFactoryPostProcessors→ConfigurationClassPostProcessor扫描Component、Bean解析自动配置类spring.factories中的EnableAutoConfigurationonRefresh()在 Servlet 上下文中Override protected void onRefresh() { super.onRefresh(); try { createWebServer(); // 启动内嵌 Tomcat/Jetty } }finishBeanFactoryInitialization→ 调用preInstantiateSingletons()触发所有单例 Bean 的创建包括依赖注入、PostConstruct步骤 6执行 Runner 启动完成/ 执行 CommandLineRunner / ApplicationRunner callRunners(context, applicationArguments);✅ 此时服务已完全就绪可处理请求四、启动流程全景图简化版ain() ↓ new SpringApplication() ├── 推断 Web 类型 ├── 加载 Initializers Listeners ↓ run(args) ├── starting() → ApplicationStartingEvent ├── prepareEnvironment() → 加载 application.properties ├── createApplicationContext() ├── prepareContext() → 注册主配置类 ├── refreshContext() │ ├── invokeBeanFactoryPostProcessors → 自动配置生效 │ ├── onRefresh() → 启动内嵌 Web 容器 │ └── finishBeanFactoryInitialization → 初始化所有 Bean ├── callRunners() → 执行启动后任务五、学源码有什么用实战场景举例场景利用的启动阶段扩展方式动态加载远程配置environmentPrepared实现EnvironmentPostProcessor启动耗时分析starting()/running()自定义SpringApplicationRunListener服务注册延迟ContextRefreshedEvent后监听事件确保 Bean 全部就绪自定义 BannerprepareContext阶段实现Banner接口避免循环依赖报错理解finishBeanFactoryInitialization顺序调整依赖关系或使用Lazy关注我每天5分钟带你从 Java 小白变身编程高手 点赞 关注让更多小伙伴一起进步

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询