//构造方法初始化,创建一个新的实例,这个应用程序的上下文要从指定的来源加载bean
public SpringApplication(ResourceLoaderresourceLoader, Class<?>... primarySources) {
this.sources = newLinkedHashSet();
this.bannerMode = Mode.CONSOLE;
this.logStartupInfo = true;
this.addCommandLineProperties = true;
this.headless = true;
this.registerShutdownHook = true;
this.additionalProfiles = newHashSet();
//初始化资源加载器,默认为null
this.resourceLoader = resourceLoader;
//断言要加载的资源类不能为null否则报错
Assert.notNull(primarySources, "Primary Sources must not be null");
//初始化主要加载资源并去重
this.primarySources = newLinkedHashSet(Arrays.asList(primarySources));
//判断当前应用程序的类型 NONE/SERVLET/REACTIVE
this.webApplicationType = this.deduceWebApplicationType();
//加载所有的初始化容器,设置应用上下文初始化器,从"META-INF/spring.factories"读取ApplicationContextInitializer类的实例名称集合并去重,并进行set去重。(一共5个)
this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class));
//设置监听器,从"META-INF/spring.factories"读取ApplicationListener类的实例名称集合并去重,并进行set去重。(一共10个)
this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class));
//推断主入口应用类,通过当前调用栈,获取Main方法所在类,并赋值给mainApplicationClass
this.mainApplicationClass = this.deduceMainApplicationClass();
}
//启动流程
// springboot启动的运行方法,可以看到主要是各种运行环境的准备工作
public ConfigurableApplicationContext run(String... args) {
//创建并启动计时监控类
//设置当前任务的id和启动的时间,方便后续的时候进行计时的操作
StopWatch stopWatch = new StopWatch();
stopWatch.start();
//初始化上下文
//初始化异常报告集合
ConfigurableApplicationContext context = null;
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList();
//设置系统属性“java.awt.headless”
//默认为true,用于运行headless服务器,进行简单的图像处理,多用于在缺少显示屏、键盘或者鼠标时的系统配置,很多监控工具如jconsole 需要将该值设置为true
this.configureHeadlessProperty();
//注册linsteners,创建所有spring运行监听器并发布应用启动事件,简单说的话就是获取SpringApplicationRunListener类型的实例(EventPublishingRunListener对象),并封装进SpringApplicationRunListeners对象,然后返回这个SpringApplicationRunListeners对象。说的再简单点,getRunListeners就是准备好了运行时监听器EventPublishingRunListener。
//记载spring.factoris文件中的你内容
//获取文件中对应类的全路径
//根据反射得到具体的实体类对象
//生成对应的对象之后再返回给调用者
SpringApplicationRunListeners listeners = this.getRunListeners(args);
//每次监听器在实际做操作的时候都会执行listeners.starting()
this.initialMulticaster.multicastEvent
//匹配不同类型的事件,然后从所有的监听器中把不符合条件的监听给过滤掉
//符合条件的监听器会循环执行具体的自己的处理逻辑
listeners.starting();
try {
//初始化默认参数应用类
//加载命令行的参数值,解析在命令行中通过--key=value输入的属性值,封装到ApplicationArguments对象中
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
//根据运行监听器和应用参数来准备spring环境
ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments);
//设置系统属性,保证某些bean不会添加到准备的环境中(设置忽略的参数)
this.configureIgnoreBeanInfo(environment);
//创建banner打印类
Banner printedBanner = this.printBanner(environment);
//创建应用上下文对象,根据当前应用类型选择创建什么类型的上下文 servlet,reactive,none
context = this.createApplicationContext();
//设置异常报告对象,用来支持报告关于启动的错误
this.getSpringFactoriesInstances(SpringBootExceptionReporter.class, newClass[]{
ConfigurableApplicationContext.class
},context);
//准备当前上下文对象,包含一个关键操作,将启动类注入容器,为后续开启自动化提供基础
//设置初始化进行执行,向beanfactory中注入了三个postprocessor的对象,后续在自动装配的时候会用到applyInitializers(context);
listeners.contextPrepared(context);
//加载很多资源配置,自动装配在此环节完成load(context, sources.toArray(new Object[0]));
listeners.contextLoaded(context);
this.prepareContext(context, environment, listeners, applicationArguments, printedBanner);
//刷新应用上下文
this.refreshContext(context);
//应用上下文刷新后置操作做一些扩展功能
this.afterRefresh(context, applicationArguments);
//计时结束,并打印程序所用时长
stopWatch.stop();
//输出日志,记录执行的主类目和事件信息
if (this.logStartupInfo) {
(newStartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch);
}
//启动所有的监听器对象
listeners.started(context);
//执行所有的runner运行器
this.callRunners(context, applicationArguments);
} catch (Throwablevar9) {
//处理失败的操作
this.handleRunFailure(context, listeners, exceptionReporters, var9);
thrownewIllegalStateException(var9);
}
//启动完成调用,发布应用上下文就绪事件
listeners.running(context);
//返回应用上下文
return context;
}
springboot执行流程
于 2020-01-08 00:04:40 首次发布