主要看下new SpringApplication逻辑和run方法逻辑:
new SpringApplication逻辑:
进入run方法后,会 new 一个SpringApplication 对象,创建这个对象的构造函数做了一些准备工作,核心步骤如下:
确定应用程序类型
在SpringApplication的构造方法内,首先会通过 WebApplicationType.deduceFromClasspath(); 方法判断当前应用程序的容器,默认使用的是Servlet 容器,除了servlet之外,还有NONE 和 REACTIVE (响应式编程);
加载所有的初始化器
从 META-INF/spring.factories 配置文件中加载实现了ApplicationContextInitializer接口的类
加载所有的监听器
从 META-INF/spring.factories 配置文件中加载实现了 ApplicationListener 接口的类
设置程序运行的主类,为后面的扫包作准备。
run方法逻辑:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 | public ConfigurableApplicationContext run(String... args) { //创建stopWatch,统计run方法执行耗时 StopWatch stopWatch = new StopWatch(); //开始启动计时 stopWatch.start(); ConfigurableApplicationContext context = null ; Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList(); this .configureHeadlessProperty(); //加载所有SpringApplicationRunListener监听器 SpringApplicationRunListeners listeners = this .getRunListeners(args); //调用SpringApplicationRunListener的starting方法 listeners.starting(); Collection exceptionReporters; try { //将springApplication的启动参数封装为ApplicationArguments ApplicationArguments applicationArguments = new DefaultApplicationArguments(args); //创建Springboot应用使用的环境变量,内部会根据webApplicationType创建不同的环境变量 //这里会创建StandardServletEnvironment ConfigurableEnvironment environment = this .prepareEnvironment(listeners, applicationArguments); this .configureIgnoreBeanInfo(environment); //打印banner Banner printedBanner = this .printBanner(environment); //根据webApplicationType创建AnnotationConfigServletWebServerApplicationContext对象 context = this .createApplicationContext(); //加载springboot的异常报告对象,当springboot启动抛异常时,会通过该对象打印错误日志 exceptionReporters = this .getSpringFactoriesInstances(SpringBootExceptionReporter. class , new Class[]{ConfigurableApplicationContext. class }, context); //准备上下文环境 this .prepareContext(context, environment, listeners, applicationArguments, printedBanner); //调用applicationContext的refresh方法,启动整个spring应用程序,springboot自动装配也是在此流程里面进行的 this .refreshContext(context); //留给用户拓展 this .afterRefresh(context, applicationArguments); //结束计时器 stopWatch.stop(); if ( this .logStartupInfo) { ( new StartupInfoLogger( this .mainApplicationClass)).logStarted( this .getApplicationLog(), stopWatch); } //发布上下文准备就绪事件,调用SpringApplicationListener对象的started监听方法 listeners.started(context); //回调spring中的ApplicationRunner对象和CommandLineRunner this .callRunners(context, applicationArguments); } catch (Throwable var10) { //抛出异常,则使用SpringBootExceptionReporter打印异常报告 this .handleRunFailure(context, var10, exceptionReporters, listeners); throw new IllegalStateException(var10); } try { //启动成功,调用SpringApplicationListener对象的running方法 listeners.running(context); return context; } catch (Throwable var9) { //抛出异常,则使用SpringBootExceptionReporter打印异常报告 this .handleRunFailure(context, var9, exceptionReporters, (SpringApplicationRunListeners) null ); throw new IllegalStateException(var9); } } |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南