概述
springboot启动类
package com.ahs.ahsaccount;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class AhsAccountApplication {public static void main(String[] args) {SpringApplication.run(AhsAccountApplication.class, args);}}
run方法
//SpringApplication.class
public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {return new SpringApplication(primarySources).run(args);}
实例方法
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {this.resourceLoader = resourceLoader;Assert.notNull(primarySources, "PrimarySources must not be null"); 将启动类放入primarySourcesthis.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));//根据classpath 下的类,推算当前web应用类型(REACTIVE, servlet)this.webApplicationType = WebApplicationType.deduceFromClasspath();//去spring.factories 中去获取所有key:org.springframework.context.ApplicationContextInitializersetInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));//去spring.factories 中去获取所有key: org.springframework.context.ApplicationListenersetListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));//根据main方法推算出mainApplicationClassthis.mainApplicationClass = deduceMainApplicationClass();}
获取启动类
获取web应用类型
读取了ApplicationContextInitializer ,ApplicationListener
根据main推算出所在的类
run方法
// SpringApplication.javapublic ConfigurableApplicationContext run(String... args) {// 创建 StopWatch 对象,并启动。StopWatch 主要用于简单统计 run 启动过程的时长。StopWatch stopWatch = new StopWatch();//是记录了启动开始时间stopWatch.start();ConfigurableApplicationContext context = null;Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();// 配置 headless 属性configureHeadlessProperty();// 去spring.factroies中读取了SpringApplicationRunListener 的组件, 就是用来发布事件或者运行监听器SpringApplicationRunListeners listeners = getRunListeners(args);//发布1.ApplicationStartingEvent事件,在运行开始时发送listeners.starting();try {// 创建 ApplicationArguments 对象ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);// 加载属性配置。执行完成后,所有的 environment 的属性都会加载进来,包括 application.properties 和外部的属性配置。预初始化环境: 读取环境变量,读取配置文件信息(基于监听器)ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);// 忽略beaninfo的beanconfigureIgnoreBeanInfo(environment);// 打印Banner 横幅Banner printedBanner = printBanner(environment);// 创建 Spring 容器。 根据webApplicationType创建Spring上下文context = createApplicationContext();// 异常报告器exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,new Class[] { ConfigurableApplicationContext.class }, context);// 主要是调用所有初始化类的 initialize 方法,/预初始化spring上下文prepareContext(context, environment, listeners, applicationArguments,printedBanner);// 初始化 Spring 容器。ioc流程refreshContext(context);// 执行 Spring 容器的初始化的后置逻辑。默认实现为空。afterRefresh(context, applicationArguments);// 停止 StopWatch 统计时长stopWatch.stop();// 打印 Spring Boot 启动的时长日志。if (this.logStartupInfo) {new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);}// 通知 SpringApplicationRunListener 的数组,Spring 容器启动完成。listeners.started(context);// 调用 ApplicationRunner 或者 CommandLineRunner 的运行方法。callRunners(context, applicationArguments);} catch (Throwable ex) {// 如果发生异常,则进行处理,并抛出 IllegalStateException 异常handleRunFailure(context, ex, exceptionReporters, listeners);throw new IllegalStateException(ex);}// 通知 SpringApplicationRunListener 的数组,Spring 容器运行中。try {listeners.running(context);} catch (Throwable ex) {// 如果发生异常,则进行处理,并抛出 IllegalStateException 异常handleRunFailure(context, ex, exceptionReporters, null);throw new IllegalStateException(ex);}return context;
}
prepareEnvironment
// SpringApplication.javaprivate ConfigurableEnvironment prepareEnvironment(SpringApplicationRunListeners listeners, ApplicationArguments applicationArguments) {// Create and configure the environment// 创建 ConfigurableEnvironment 对象,并进行配置//根据webApplicationType 创建Environment 创建就会读取: java环境变量和系统环境变量ConfigurableEnvironment environment = getOrCreateEnvironment();configureEnvironment(environment, applicationArguments.getSourceArgs());// 通知 SpringApplicationRunListener 的数组,环境变量已经准备完成。//发布了ApplicationEnvironmentPreparedEvent 的监听器 读取了全局配置文件listeners.environmentPrepared(environment);// 绑定 environment 到 SpringApplication 上bindToSpringApplication(environment);// 如果非自定义 environment ,则根据条件转换if (!this.isCustomEnvironment) {environment = new EnvironmentConverter(getClassLoader()).convertEnvironmentIfNecessary(environment, deduceEnvironmentClass());}// 如果有 attach 到 environment 上的 MutablePropertySources ,则添加到 environment 的 PropertySource 中。ConfigurationPropertySources.attach(environment);return environment;
}
prepareContext
// SpringApplication.javaprivate void prepareContext(ConfigurableApplicationContext context,ConfigurableEnvironment environment, SpringApplicationRunListeners listeners,ApplicationArguments applicationArguments, Banner printedBanner) {// <1> 设置 context 的 environment 属性context.setEnvironment(environment);// <2> 设置 context 的一些属性postProcessApplicationContext(context);// <3> 初始化 ApplicationContextInitializer//拿到之前读取到所有ApplicationContextInitializer的组件, 循环调用initialize方法applyInitializers(context);// <4> 通知 SpringApplicationRunListener 的数组,Spring 容器准备完成。listeners.contextPrepared(context);// <5> 打印日志if (this.logStartupInfo) {logStartupInfo(context.getParent() == null);logStartupProfileInfo(context);}// Add boot specific singleton beans// <6> 设置 beanFactory 的属性ConfigurableListableBeanFactory beanFactory = context.getBeanFactory();beanFactory.registerSingleton("springApplicationArguments", applicationArguments);if (printedBanner != null) {beanFactory.registerSingleton("springBootBanner", printedBanner);}if (beanFactory instanceof DefaultListableBeanFactory) {((DefaultListableBeanFactory) beanFactory).setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);}// Load the sources// <7> 加载 BeanDefinition 们Set<Object> sources = getAllSources();Assert.notEmpty(sources, "Sources must not be empty");load(context, sources.toArray(new Object[0]));// <8> 通知 SpringApplicationRunListener 的数组,Spring 容器加载完成。listeners.contextLoaded(context);
}
refreshContext
// SpringApplication.javaprivate void refreshContext(ConfigurableApplicationContext context) {// <1> 开启(刷新)Spring 容器refresh(context);// <2> 注册 ShutdownHook 钩子if (this.registerShutdownHook) {try {context.registerShutdownHook();} catch (AccessControlException ex) {// Not allowed in some environments.}}
}
callRunners
扩展点
// SpringApplication.javaprivate void callRunners(ApplicationContext context, ApplicationArguments args) {// <1> 获得所有 Runner 们List<Object> runners = new ArrayList<>();// <1.1> 获得所有 ApplicationRunner Bean 们runners.addAll(context.getBeansOfType(ApplicationRunner.class).values());// <1.2> 获得所有 CommandLineRunner Bean 们runners.addAll(context.getBeansOfType(CommandLineRunner.class).values());// <1.3> 排序 runnersAnnotationAwareOrderComparator.sort(runners);// <2> 遍历 Runner 数组,执行逻辑for (Object runner : new LinkedHashSet<>(runners)) {if (runner instanceof ApplicationRunner) {callRunner((ApplicationRunner) runner, args);}if (runner instanceof CommandLineRunner) {callRunner((CommandLineRunner) runner, args);}}
}
总结
1、初始化SpringApplication 从spring.factories 读取 listener ApplicationContextInitializer 。
2.运行run方法
3.读取 环境变量 配置信息等
4. 创建springApplication上下文:ServletWebServerApplicationContext
5. . 预初始化上下文
6.调用refresh 加载ioc容器 加载所有的自动配置类
7、创建servlet容器
8.整个流程中会多次调用很多监听器对外进行