springboot项目整个的启动流程
文章目录
- SpringBootApplication注解
- 自动配置核心类SpringFactoriesLoader
- 整体启动流程
- 初始化SpringApplication类
- 执行核心run方法
SpringBootApplication注解
不从注解讲起都是耍流氓@SpringBootApplication注解@SpringBootApplication是一个复合注解,它由三个注解组成。
@SpringBootConfiguration(打开是@Configuration):表明这是一个Java配置类。
@EnableAutoConfiguration:自动配置注解,会将所有符合自动配置条件的@Configuration 配置加载到 IOC 容器。
@ComponentScan:扫描注解,自动扫描符合条件的组件(@Service、@Component)或者 bean 定义,记载到 IOC 容器中。
自动配置核心类SpringFactoriesLoader
上面在说@EnableAutoConfiguration的时候有说META-INF下的spring.factories文件,那么这个文件是怎么被spring加载到的呢,其实就是SpringFactoriesLoader类。SpringFactoriesLoader是一个供Spring内部使用的通用工厂装载器,SpringFactoriesLoader里有两个方法,
// 加载工厂类并实例化
public static <T> List<T> loadFactories(Class<T> factoryClass, ClassLoader classLoader) {}
// 加载工厂类的类名
public static List<String> loadFactoryNames(Class<?> factoryClass, ClassLoader classLoader) {}
在这个SpringBoot应用启动过程中,SpringFactoriesLoader做了以下几件事:
- 加载所有META-INF/spring.factories中的Initializer
- 加载所有META-INF/spring.factories中的Listener
- 加载EnvironmentPostProcessor(允许在Spring应用构建之前定制环境配置)接下来
- 加载Properties和YAML的PropertySourceLoader(针对SpringBoot的两种配置文件的加载器)
- 各种异常情况的FailureAnalyzer(异常解释器)
- 加载SpringBoot内部实现的各种AutoConfiguration
- 模板引擎TemplateAvailabilityProvider(如Freemarker、Thymeleaf、Jsp、Velocity等)
总得来说,SpringFactoriesLoader和@EnableAutoConfiguration配合起来,整体功能就是查找spring.factories文件,加载自动配置类。
整体启动流程
在我们执行入口类的main方法之后,运行SpringApplication.run,后面new了一个SpringApplication对象,然后执行它的run方法。
public static ConfigurableApplicationContext run(Object[] sources, String[] args) {return new SpringApplication(sources).run(args);
}
初始化SpringApplication类
创建一个SpringApplication对象时,会调用它自己的initialize方法
private void initialize(Object[] sources) {if (sources != null && sources.length > 0) {this.sources.addAll(Arrays.asList(sources));}// 根据标志类javax.servlet.Servlet,org.springframework.web.context.ConfigurableWebApplicationContext是否存在,判断是否是web环境this.webEnvironment = deduceWebEnvironment();// 通过SpringFactoriesLoader,获取到所有META-INF/spring.factories中的ApplicationContextInitializer,并实例化setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));// 通过SpringFactoriesLoader,获取到所有META-INF/spring.factories中的ApplicationListener,并实例化setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));// 获取执行当前main方法的类,也就是启动类this.mainApplicationClass = deduceMainApplicationClass();
}
执行核心run方法
初始化initialize方法执行完之后,会调用run方法,开始启动SpringBoot。
public ConfigurableApplicationContext run(String... args) {// 启动任务执行的时间监听器StopWatch stopWatch = new StopWatch();stopWatch.start();ConfigurableApplicationContext context = null;FailureAnalyzers analyzers = null;// 设置系统java.awt.headless属性,确定是否开启headless模式(默认开启headless模式)configureHeadlessProperty();// 通过SpringFactoriesLoader,获取到所有META-INF/spring.factories下的SpringApplicationRunListeners并实例化SpringApplicationRunListeners listeners = getRunListeners(args);// 开始广播启动listeners.started();try {// 创建SpringBoot默认启动参数对象ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);// 根据启动参数创建并配置Environment(所有有效的配置,如Profile),并遍历所有的listeners,广播启动环境已准备ConfigurableEnvironment environment = prepareEnvironment(listeners,applicationArguments);// 打印启动图案Banner printedBanner = printBanner(environment);// 根据标志类(上面有提到过),创建对应类型的ApplicationContextcontext = createApplicationContext();// 创建异常解析器(当启动失败时,由此解析器处理失败结果)analyzers = new FailureAnalyzers(context);// 准备Spring上下文环境// 在这个方法中,主要完成了以下几件事:// 1、设置SpringBoot的环境配置(Environment)// 2、注册Spring Bean名称的序列化器BeanNameGenerator,并设置资源加载器ResourceLoader// 3、加载ApplicationContextInitializer初始化器,并进行初始化// 4、统一将上面的Environment、BeanNameGenerator、ResourceLoader使用默认的Bean注册器进行注册prepareContext(context, environment, listeners, applicationArguments,printedBanner);// 注册一个关闭Spring容器的钩子refreshContext(context);// 获取当前所有ApplicationRunner和CommandLineRunner接口的实现类,执行其run方法// ApplicationRunner和CommandLineRunner功能基本一样,在Spring容器启动完成时执行,唯一不同的是ApplicationRunner的run方法入参是ApplicationArguments,而CommandLineRunner是String数组afterRefresh(context, applicationArguments);// 通知所有listener,Spring容器启动完成listeners.finished(context, null);// 停止时间监听器stopWatch.stop();if (this.logStartupInfo) {new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);}return context;} catch (Throwable ex) {// 启动有异常时,调用异常解析器解析异常信息,根据异常级别,判断是否退出Spring容器handleRunFailure(context, listeners, analyzers, ex);throw new IllegalStateException(ex);}
}
- 首先遍历执行所有通过SpringFactoriesLoader,在当前classpath下的META-INF/spring.factories中查找所有可用的SpringApplicationRunListeners并实例化。调用它们的starting()方法,通知这些监听器SpringBoot应用启动。
- 创建并配置当前SpringBoot应用将要使用的Environment,包括当前有效的PropertySource以及Profile。
- 遍历调用所有的SpringApplicationRunListeners的environmentPrepared()的方法,通知这些监听器SpringBoot应用的Environment已经完成初始化。
- 打印SpringBoot应用的banner,SpringApplication的showBanner属性为true时,如果classpath下存在banner.txt文件,则打印其内容,否则打印默认banner。
- 根据启动时设置的applicationContextClass和在initialize方法设置的webEnvironment,创建对应的applicationContext。
- 创建异常解析器,用在启动中发生异常的时候进行异常处理(包括记录日志、释放资源等)。
- 设置SpringBoot的Environment,注册Spring Bean名称的序列化器BeanNameGenerator,并设置资源加载器ResourceLoader,通过SpringFactoriesLoader加载ApplicationContextInitializer初始化器,调用initialize方法,对创建的ApplicationContext进一步初始化。
- 调用所有的SpringApplicationRunListeners的contextPrepared方法,通知这些Listener当前ApplicationContext已经创建完毕。
- 最核心的一步,将之前通过@EnableAutoConfiguration获取的所有配置以及其他形式的IoC容器配置加载到已经准备完毕的ApplicationContext。
- 调用所有的SpringApplicationRunListener的contextLoaded方法,加载准备完毕的ApplicationContext。
- 调用refreshContext,注册一个关闭Spring容器的钩子ShutdownHook,当程序在停止的时候释放资源(包括:销毁Bean,关闭SpringBean的创建工厂等)
- 获取当前所有ApplicationRunner和CommandLineRunner接口的实现类,执行其run方法。遍历所有的SpringApplicationRunListener的finished()方法,完成SpringBoot的启动。
springboot项目整个的启动流程相关推荐
- Linux上搭建SpringBoot项目部署环境和流程分享
Linux上搭建SpringBoot项目部署环境和流程分享 背景介绍 环境搭建 1.JDK 2.Mysql 数据库 3.Redis 4.Nginx 项目部署 总结 背景介绍 最近在开发一个 Sprin ...
- SpringBoot 项目tomcat插件启动报错 java.lang.NoClassDefFoundError: javax/el/ELManager
问题描述: SpringBoot项目 tomcat插件启动出现下面的问题: ERROR 2021-04-07 08:42:03,129 org.springframework.boot.SpringA ...
- springboot项目打war包流程
目前,前后端分离的架构已成主流,因此使用springboot构建应用是非常快速的,项目发布到服务器上的时候,只需要打成一个jar包,然后通过命令 : java -jar jar包名称即可启动服务了: ...
- 2:IDEA生成springboot项目,修改启动图标和网页端口
文章目录 1:IDEA生成springboot项目 2:修改启动图标 3:修改网页端口 1:IDEA生成springboot项目 新建 spring initializer 选择custome htt ...
- springboot项目创建和启动
一.创建springboot项目 Spring Initializr: https://start.spring.io/ 通过这个网站创建springboot项目 选择基本依赖,可创建 二.启动项目 ...
- SpringBoot项目用tomcat启动,没有报错,控制台只输出org.apache.catalina.startup.catalina.start server startup in xxxms
背景:最近在使用SpringBoot项目过程中,代码写好测试完,部署到服务器上启动使用外置的tomcat启动,控制台只输出org.apache.catalina.startup.catalina.st ...
- springboot项目jar包启动脚本
当工具用习惯了.也就懒的去关心底层的东西了.项目部署的时候,用习惯了jenkins也就不关心运维写的脚本了.但是当工具出问题,那就要从最基础的脚本来部署项目.脚本我也不太懂,在这里只是与大家一起分享启 ...
- webpack项目配置与启动流程
创建项目 npm init //然后依次填写相应信息 {"name": "test","version": "1.0.0" ...
- Springboot项目使用jdk17启动报错:module java.base does not “opens java.lang.invoke“
解决方法: 启动参数增加 –add-opens java.base/java.lang.invoke=ALL-UNNAMED
最新文章
- ThinkPHP控制器
- 【Linux开发】linux设备驱动归纳总结(六):3.中断的上半部和下半部——tasklet...
- CH - 6901 骑士放置(二分图最大独立集-二分图最大匹配+奇偶拆点)
- matlab中欠定方程组超定方程组_《数值天气预报》:球坐标系中的基本方程组
- 名图1.8智能隐藏功能_7年后再度回归 全新一代名图“大”不同_搜狐汽车
- win10更新后开不了机_win7在线更新window10系统
- python查看数据类型type_python——获取数据类型:type()、isinstance()的使用方法:...
- zookeeper启动后查看状态的Error contacting service. It is probably not running.错误
- 诺基亚手机: 诺基亚N9将在下月19日开卖 售价4400元
- XP经典壁纸,多少人曾爱慕你年轻时的容颜
- pip学习20200810
- html修改导航栏字体大小,CSS 制作网页导航条(下)
- 某宝双十一自动养猫,解放你的双手得喵币
- 【求助】如何在移动固态硬盘上装一个完美的移动系统
- Python中ArcPy实现Excel时序数据读取、反距离加权IDW插值与批量掩膜
- ds3617xs 华擎J3455 无线网卡m.2装千兆网卡组成链路聚合
- 新手上路必备的 DAX 函数(下)
- 博世BOSCH EDI DESADV发货通知详解
- html图片怎么做成链接,HTML的链接代码怎么做?HTML的图片链接怎么制作?
- 丢人了,我都不知道4D啊