[Springboot2.1.5学习笔记]Springboot2.1.5启动机制源码分析

94 篇文章 2 订阅
8 篇文章 0 订阅

一、启动配置原理

启动流程分析:

1.debug方式启动springboot

在这里插入图片描述

2.run springApplication

在这里插入图片描述
上面的run方法调用下面的重载run方法,参数从Class<?>primarySource

转换成 Class<?>[] primarySources,具体调用下面的重载方法返回一个ConfigurableApplicationContext对象

3.初始化一个SpringApplication容器,参数是primarySources

在这里插入图片描述

调用其有参构造方法

在这里插入图片描述

4.开始初始化参数

 public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
     	//初始化一个set
        this.sources = new LinkedHashSet();
     	//开始初始化参数
        this.bannerMode = Mode.CONSOLE;
        this.logStartupInfo = true;
        this.addCommandLineProperties = true;
        this.addConversionService = true;
        this.headless = true;
        this.registerShutdownHook = true;
        this.additionalProfiles = new HashSet();
        this.isCustomEnvironment = false;
        this.resourceLoader = resourceLoader;
     	//非空声明
        Assert.notNull(primarySources, "PrimarySources must not be null");
     	//将primarySources所有参数存入primarySources属性中
        this.primarySources = new LinkedHashSet(Arrays.asList(primarySources));
     	//查询有没有DispatcherHandler这样的组件,判断是否为web环境
        this.webApplicationType = WebApplicationType.deduceFromClasspath();
      	//从类路径下找到META-INF/spring.factories配置的所有ApplicationContextInitializer保存起来
        this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class));
     	//从类路径下找到META-INF/spring.factories配置的所有ApplicationListener保存起来
        this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class));
     	//查询所有配有main的主方法类
        this.mainApplicationClass = this.deduceMainApplicationClass();
    }

这里以this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class));为例分析

  1. 方法调用是将获得的Spring工厂实例化初始化加载器initializers加入到这个SpringApplication类的集合initializers

在这里插入图片描述

​ 2. 那么这些initializers从何而来?那就是this.getSpringFactoriesInstances(ApplicationContextInitializer.class).查看getSpringFactoriesInstances方法的调用,就是进一步调用this.getSpringFactoriesInstances

在这里插入图片描述

​ 3.那么来到getSpringFactoriesInstances方法,发现调用SpringFactoriesLoader类加载器去加载工厂

在这里插入图片描述

​ 4.可以看到类加载器加载的是location是"META-INF/spring.factories"
在这里插入图片描述

​ 5.加载的就是我们自动配置文件

在这里插入图片描述

​ 6.其他的也同理不做赘述,进行自动配置初始化后,SpringApplication进行了初始化,并且放入集合中待激活

5.run方法运行

    public ConfigurableApplicationContext run(String... args) {
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        ConfigurableApplicationContext context = null;
        Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList();
        this.configureHeadlessProperty();
        //获取之前已经初始化好的监听器
        SpringApplicationRunListeners listeners = this.getRunListeners(args);
        //开启监听器
        listeners.starting();

        Collection exceptionReporters;
        try {
            //封装命令行参数
            ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
            //准备环境,准备完成监听器也会回调listeners.environmentPrepared((ConfigurableEnvironment)environment);
            ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments);
            this.configureIgnoreBeanInfo(environment);
            //根据环境创建printedBanner
            Banner printedBanner = this.printBanner(environment);
            //创建容器,根据环境判断是普通容器还是web容器
            context = this.createApplicationContext();
            //加载SpringBootExceptionReporter异常上报实例,放入上下文环境中
            exceptionReporters = this.getSpringFactoriesInstances(SpringBootExceptionReporter.class, new Class[]{ConfigurableApplicationContext.class}, context);
            //准备上下文环境,最后回调listeners.contextLoaded(context);
            this.prepareContext(context, environment, listeners, applicationArguments, printedBanner);
            //ioc容器根据上下文环境,加载嵌入式服务器,配置,组件等等,控制台有输出
            this.refreshContext(context);
            this.afterRefresh(context, applicationArguments);
            stopWatch.stop();
            if (this.logStartupInfo) {
                (new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch);
            }
			//回调spirngApplicationListener的Start方法
            listeners.started(context);
            //调用下叙两句
            //runners.addAll(context.getBeansOfType(ApplicationRunner.class).values());
        	//runners.addAll(context.getBeansOfType(CommandLineRunner.class).values());
            //从ioc容器中获取所有的ApplicationRunner和CommandLineRunner进行回调
       		//ApplicationRunner先回调,CommandLineRunner再回调
            this.callRunners(context, applicationArguments);
        } catch (Throwable var10) {
            this.handleRunFailure(context, var10, exceptionReporters, listeners);
            throw new IllegalStateException(var10);
        }

        try {
            //监听器run
            listeners.running(context);
            //整个springboot开始run,最后返回容器
            return context;
        } catch (Throwable var9) {
            this.handleRunFailure(context, var9, exceptionReporters, (SpringApplicationRunListeners)null);
            throw new IllegalStateException(var9);
        }
    }

启动源码分析大致就是这些,如有问题请您批评指正~

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值