springboot源码剖析(一) 总体启动流程

  前言

     之前阅读STL(C++)源码的时候,有所感悟: 大佬的代码总会实践到部分设计模式、新型语法特性,亦或是精巧的算法和数据结构。

          读源码的技巧:大局入手,之后细细品味,重点地方做到逐行阅读。

          故学习源码也是提升自己认知和能力的一种途径,本篇章主要介绍springboot源码相关。

          链接:

          springboot源码剖析(一) 总体启动流程

          springboot源码剖析(二) 事件发布

          springboot源码剖析(三) 环境配置

          springboot源码剖析(四) 上下文启动

 


 

  概念

          Spring Boot是一个基于Spring的套件,它帮我们预组装了Spring的一系列组件,以便以尽可能少的代码和配置来开发基于Spring的Java应用程序。        


       源码剖析 

     源码剖析不可避免要贴大量代码,逐行贴上注释解释流程,重要的接口我会放在后面解释。

           总体启动流程

           1.  构造

// springApplication.class 构造
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
    // 初始化部分属性
    ...
    // 主类设置为入口传参的类
    this.primarySources = new LinkedHashSet(Arrays.asList(primarySources));
    // web应用类型SERVLET
    this.webApplicationType = WebApplicationType.deduceFromClasspath();
    // ★ 加载初始化器类和监听器类
    // 扫描类路径下META-INFO/spring.factories中的org.springframework.context.ApplicationContextInitializer
    this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class));
    // 扫描类路径下META-INFO/spring.factories中的org.springframework.context.ApplicationListener
    this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class));
    // 推导main函数的入口类
    this.mainApplicationClass = this.deduceMainApplicationClass();
}

           2.  启动

// springApplication.class 启动
public ConfigurableApplicationContext run(String... args) {
    // 秒表类,创建计时器
    StopWatch stopWatch = new StopWatch();
    // 计时开始
    stopWatch.start();
    ConfigurableApplicationContext context = null;
    Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList();
    // 配置headless模式,表示运行在服务器器端,在没有显示器器和鼠标键盘的模式下工作,模拟输入输出设备功能
    this.configureHeadlessProperty();
    // 扫描META-INF/spring-factories 中的org.springframework.boot.SpringApplicationRunListener,并初始化广播器
    SpringApplicationRunListeners listeners = this.getRunListeners(args);
    // ★ 发布ApplicationStartingEvent事件
    listeners.starting();

    Collection exceptionReporters;
    try {
        // 解析命令行参数
        ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
        // ★ 准备环境配置
        ConfigurableEnvironment environment = this.prepareEnvironment(listeners, applicationArguments);
        // 增加系统配置参数spring.beaninfo.ignore
        this.configureIgnoreBeanInfo(environment);
        // 打印springboot图案
        Banner printedBanner = this.printBanner(environment);
        // 根据推导的应用类型, 创建一个AnnotationConfigServletWebServerApplicationContext的实例化对象,实际就是spring容器的子类实现
        context = this.createApplicationContext();
        // 异常报告类,处理异常用
        exceptionReporters = this.getSpringFactoriesInstances(SpringBootExceptionReporter.class, new Class[]{ConfigurableApplicationContext.class}, context);
        // 上下文准备
        this.prepareContext(context, environment, listeners, applicationArguments, printedBanner);
        // ★ 上下文刷新
        this.refreshContext(context);
        // 空操作
        this.afterRefresh(context, applicationArguments);
        // 计时结束
        stopWatch.stop();
        // 打印启动耗时
        if (this.logStartupInfo) {
            (new StartupInfoLogger(this.mainApplicationClass)).logStarted(this.getApplicationLog(), stopWatch);
        }
        // 发布ApplicationStartedEvent事件
        listeners.started(context);
        // 执行脚本
        this.callRunners(context, applicationArguments);
    } catch (Throwable var10) {
        this.handleRunFailure(context, var10, exceptionReporters, listeners);
        throw new IllegalStateException(var10);
    }

    try {
        // 发布ApplicationReadyEvent事件
        listeners.running(context);
        return context;
    } catch (Throwable var9) {
        this.handleRunFailure(context, var9, exceptionReporters, (SpringApplicationRunListeners)null);
        throw new IllegalStateException(var9);
    }
}

    本文重点是getSpringFactoriesInstances方法,用来查找并获取某个工厂实例

private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
        ClassLoader classLoader = this.getClassLoader();
// 1. classLoader搜索META-INF/spring.factories里匹配的类 Set
<String> names = new LinkedHashSet(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
// 2. 通过反射实例化这些类 List
<T> instances = this.createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names); AnnotationAwareOrderComparator.sort(instances); return instances; }

          

 

posted @ 2022-10-30 13:42  Duikerdd  阅读(58)  评论(0编辑  收藏  举报