暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

SpringBoot 启动分析(二)--启动主流程

coderbee笔记 2019-06-10
172

1. initialize 方法

SpringApplication
的构造函数只调用了 initialize
方法:


private void initialize(Object[] sources) {
if (sources != null && sources.length > 0) {
// 把应用指定的配置类加入配置扫描的启动来源
this.sources.addAll(Arrays.asList(sources));
}


// 判断应用是否是 web 应用,主要用于决定采用哪种具体的上下文实现
this.webEnvironment = deduceWebEnvironment();


// 利用定制的 SPI 实现 SpringFactoriesLoader 加载 ApplicationContextInitializer 的所有实现并设置到 initializers 属性
setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));


// 利用定制的 SPI 实现 SpringFactoriesLoader 加载 ApplicationListener 的所有实现并设置到 listeners 属性
setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));


// 找出启动类:线程栈上 main 方法所处的类
this.mainApplicationClass = deduceMainApplicationClass();


}


该方法的逻辑主要如下:

  1. 把启动类加入 sources 属性。

  2. 判断是否是 web 应用并设置到 webEnvironment 属性。

  3. 加载所有的 ApplicationContextInitializer 并设置到 initializers 属性。

  4. 加载所有的 ApplicationListener 并设置到 listeners 属性。

  5. 找出 main 类设置到 mainApplicationClass。


2. run 方法


public ConfigurableApplicationContext run(String... args) {
// StopWatch 主要用来统计应用的启动时间
StopWatch stopWatch = new StopWatch();
stopWatch.start();
ConfigurableApplicationContext context = null;
FailureAnalyzers analyzers = null;


// 配置 AWT 的 headless 属性
configureHeadlessProperty();


// 初始化事件广播器,用于广播事件
SpringApplicationRunListeners listeners = getRunListeners(args);


// 触发 SpringApplicationRunListener.starting 方法
// 向 ApplicationListener 广播 ApplicationStartedEvent 事件
listeners.starting();
try {
// 封装命令行参数,后面会注册到上下文里
ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);


// 创建并准备 Environment
ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);


// 打印 Banner
Banner printedBanner = printBanner(environment);


// 创建 ApplicationContext
context = createApplicationContext();


// 创建失败分析器
analyzers = new FailureAnalyzers(context);


//
prepareContext(context, environment, listeners, applicationArguments, printedBanner);


// 刷新上下文,加载所有的Bean定义并实例化非延迟加载的单例Bean
refreshContext(context);


// 获取所有的 ApplicationRunner 和 CommandLineRunner 并执行其回调
afterRefresh(context, applicationArguments);


// 广播 ApplicationReadyEvent或ApplicationFailedEvent事件
listeners.finished(context, null);


// 终止计时
stopWatch.stop();


if (this.logStartupInfo) {
new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
}
return context;
} catch (Throwable ex) {
handleRunFailure(context, listeners, analyzers, ex);
throw new IllegalStateException(ex);
}


}


run 方法的核心逻辑:

  1. 创建 StopWatch 用于记录启动耗时;

  2. 创建并准备 Enviroment。加载所有的配置文件和处理 Profile 。

  3. 创建并准备 ApplicationContext ,把 ConfigurationClassPostProcessor
    注册到上下文底层的 BeanFacotry

  4. 刷新 ApplicationContext。

  5. 获取所有的 ApplicationRunner
    CommandLineRunner
    并执行其回调。

  6. 广播 ApplicationReadyEvent或ApplicationFailedEvent事件。


这个流程非常简单,不涉及具体的配置文件解析、加载,bean 定义扫描、解析、加载、实例化 bean 等。就是 SpringBoot 特有的流程,比如打印 Banner、回调 Runner 方法,中间适时广播事件。



欢迎关注我的微信公众号: coderbee笔记,可以更及时回复你的讨论。


文章转载自coderbee笔记,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论