1.run启动
2020-09-28 本文已影响0人
山海树
1.调用run方法,最终会返回ConfigurableApplicationContext 对象
public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
return run(new Class<?>[] { primarySource }, args);
}
ConfigurableApplicationContext 类是一个SPI的接口,继承了ApplicationContext,Lifecycle,Closeable三个类,这里封装了配置和生命周期方法,以避免客户端显式的操作applicationContext,当前方法只能通过启动和停止代码来使用该对象。
public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
return new SpringApplication(primarySources).run(args);
}
接下来需要初始化一个SpringApplication对象,传入的Class对象则是启动类对象。
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
this.resourceLoader = resourceLoader;//resourceLoader == null
Assert.notNull(primarySources, "PrimarySources must not be null");
this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
//这一步将返回一个WebApplicationType枚举类,该类有三个状态NONE,SERVLET,REACTIVE
//通过使用当前默认的类加载器,在classpath中查找是否有满足某个规则的类,如果都没加载到,则返回SERVLET
this.webApplicationType = WebApplicationType.deduceFromClasspath();
//ApplicationContextInitializer是spring组件spring-context组件中的一个接口,主要是spring ioc容器刷新之前的一个回调接口,用于处于自定义逻辑
//该方法加载系统默认配置的所有的ApplicationContextInitializer
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
//该方法加载系统默认配置的所有的ApplicationListener
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
//在当前堆栈中获得一个有main方法的主类
this.mainApplicationClass = deduceMainApplicationClass();
}
接下来使用刚构建的SpringApplication来执行run方法()
public ConfigurableApplicationContext run(String... args) {
//计时器
StopWatch stopWatch = new StopWatch();
//开始计时
stopWatch.start();
// 声明返回的变量
ConfigurableApplicationContext context = null;
// SpringBootExceptionReporter通过回调方法来记录启动是的异常报告
Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
//java.awt.headless是J2SE的一种模式用于在缺少显示屏、键盘或者鼠标时的系统配置,很多监控工具如jconsole 需要将该值设置为true,系统变量默认为true
configureHeadlessProperty();
//创建并启动监听器,args是main方法中传来的参数,用于创建监听器构造函数
SpringApplicationRunListeners listeners = getRunListeners(args);
listeners.starting();
try {
// 将main方法的入参作为配置参数保存起来,后面使用,
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
//构造容器环境
//1.根据之前webApplicationType 来确定要创建的环境类型
// 2.在创建的环境中设置配置文件、profile、监听器环境配置,
//3.将该环境绑定到SpringApplication中
ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
//4.设置配置文件中配置的需要忽略的类
configureIgnoreBeanInfo(environment);
//加载banner文件,打印banner文件
Banner printedBanner = printBanner(environment);
// 根据webApplicationType 创建容器
context = createApplicationContext();
// 实例化错误报告
exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
new Class[] { ConfigurableApplicationContext.class }, context);
//准备容器,将环境,监听器,参数,等设置好
prepareContext(context, environment, listeners, applicationArguments, printedBanner);
// 刷新容器
refreshContext(context);
// 刷新容器之后的一个回调,支持自定义操作
afterRefresh(context, applicationArguments);
//停止计时
stopWatch.stop();
// 打印启动日志
if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
}
listeners.started(context);
callRunners(context, applicationArguments);
}
catch (Throwable ex) {
//出现异常需要记录到异常报告中
handleRunFailure(context, ex, exceptionReporters, listeners);
throw new IllegalStateException(ex);
}
try {
listeners.running(context);
}
catch (Throwable ex) {
handleRunFailure(context, ex, exceptionReporters, null);
throw new IllegalStateException(ex);
}
return context;
}