SpringBoot2.1.X 启动原理

    Spring Boot 大大简化了我们的开发配置,节省了大量的时间,确实比较方便。但是对于新手来说,如果不了解其中原理,难免会遇到一些坑。

  所有的SringBoot 项目都会看到以下这个类:

1、启动类注解
 我们从注解看起,进入 @SpringBootApplication 源码可以看到,除了最基础的注解外,还增加了三个 @SpringBootConfiguration、@EnableAutoConfiguration、@ComponentScan,因此将 @SpringBootApplication 替换成以上三个也具有相同的效果,这一点,我们再前面的文章中也有提到;

源码:

@Target(ElementType.TYPE)            // 注解的适用范围,其中TYPE用于描述类、接口(包括包注解类型)或enum声明
@Retention(RetentionPolicy.RUNTIME)  // 注解的生命周期,保留到class文件中(三个生命周期)
@Documented                          // 表明这个注解应该被javadoc记录
@Inherited                           // 子类可以继承该注解
@SpringBootConfiguration             // 继承了Configuration,表示当前是注解类
@EnableAutoConfiguration             // 开启springboot的注解功能,springboot的四大神器之一,其借助@import的帮助
@ComponentScan(excludeFilters = {    // 扫描路径设置(具体使用待确认)
        @Filter(type = FilterType.CUSTOM, classes = TypeExcludeFilter.class),
        @Filter(type = FilterType.CUSTOM, classes = AutoConfigurationExcludeFilter.class) })
public @interface SpringBootApplication {
...
}

2、run 方法 简单说明

启动类先调用了 SpringApplication 的静态方法 run,跟踪进去后发现,它会先实例化 SpringApplication,然后调用 run 方法。

3、SpringApplication 方法构造过程分析说明

进入 SpringApplication 构造方法后

从 this 进入 :

通过上述代码,我们分析到 SpringApplication 实例化时有以下几个步骤:

1). 将所有 sources 加入到全局 sources 中,目前只有一个 Application。

2). 判断 可能的web应用程序类型(WebApplicationType 是一个枚举类,包含 NONE, SERVLET, REAVTIVE 三种类型)。

3). 设置应用程序初始化器 ApplicationContextInitializer,做一些初始化的工作。

4).设置应用程序事件监听器 ApplicationListener。

5).找出启动类,设置到 mainApplicationClass 中

4、run 方法 再读

回到我们进入 SpringApplication 之前的地方,再度进入run 方法

 源码:

public ConfigurableApplicationContext run(String... args) {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        ConfigurableApplicationContext context = null;
        Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
        configureHeadlessProperty();
//1.通过SpringFactoriesLoader查找并加载所有的SpringApplicationRunListeners,通过调用
//starting()方法通知所有的SpringApplicationRunListeners:应用开始启动了
        SpringApplicationRunListeners listeners = getRunListeners(args);
        listeners.starting();
        try {
//2.创建并配置当前应用将要使用的Environment
            ApplicationArguments applicationArguments = new DefaultApplicationArguments(
                    args);
            ConfigurableEnvironment environment = prepareEnvironment(listeners,
                    applicationArguments);
            configureIgnoreBeanInfo(environment);
//3.打印banner
            Banner printedBanner = printBanner(environment);
//4.根据是否是web项目,来创建不同的ApplicationContext容器
            context = createApplicationContext();
//5.创建一系列FailureAnalyzer
            exceptionReporters = getSpringFactoriesInstances(
                    SpringBootExceptionReporter.class,
                    new Class[] { ConfigurableApplicationContext.class }, context);
//6.初始化ApplicationContext
            prepareContext(context, environment, listeners, applicationArguments,
                    printedBanner);
//7.调用ApplicationContext的refresh()方法,刷新容器
            refreshContext(context);
//8.查找当前context中是否注册有CommandLineRunner和ApplicationRunner,如果有则遍历执行它们。
            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, listeners, exceptionReporters, ex);
            throw new IllegalStateException(ex);
        }
        listeners.running(context);
        return context;
    }

通过上述源码,我们可以将 run 方法执行流程分解如下:

1). 初始化 StopWatch,调用其 start 方法开始计时。
2). 调用 configureHeadlessProperty 设置系统属性 java.awt.headless,这里设置为 true,表示运行在服务器端,在没有显示器和鼠标键盘的模式下工作,模拟输入输出设备功能。

3). 遍历 SpringApplicationRunListeners 并调用 starting 方法。

4). 创建一个 DefaultApplicationArguments 对象,它持有 args 参数,就是 main 函数传进来的参数调用 prepareEnvironment 方法。
5). 打印 banner。(Spring字样)
6). 创建 Spring Boot 上下文。
7). 初始化 FailureAnalyzers。
8). 调用 prepareContext, 将上述内容加载到 上下文。
9). 调用 AbstractApplicationContext 的 refresh 方法,并注册钩子。会打印springboot的启动标志,直到server.port端口启动

10). 在容器完成刷新后,依次调用注册的 Runners。
11). 调用 SpringApplicationRunListeners 的 finished 方法。
12). 启动完成并停止计时。
13). 初始化过程中出现异常时调用 handleRunFailure 进行处理,然后抛出 IllegalStateException 异常。

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值