首页 > 编程语言 >springboot源码剖析(一) 总体启动流程

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

时间:2022-10-30 13:57:15浏览次数:48  
标签:springboot spring 剖析 listeners 源码 context new class

  前言

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

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

          故学习源码也是提升自己认知和能力的一种途径,本篇章主要介绍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; }

          

 

标签:springboot,spring,剖析,listeners,源码,context,new,class
From: https://www.cnblogs.com/Duikerdd/p/16841130.html

相关文章

  • Spring源码分析之AOP
    AOP是什么面向切面的程序设计(Aspect-orientedprogramming,AOP,又译作面向方面的程序设计、剖面导向程序设计),是计算机科学中的一种程序设计思想,旨在将横切关注点与业务主体进......
  • SpringMVC源码-DispatcherServlet初始化
    web容器启动后会实例化Servlet,会执行Servlet的init方法且只会执行一次。后续调用doService处理客户请求。DispatcherServlet的构造方法publicDispatcherServlet(){ su......
  • 第四章 SpringBoot 底层机制
    搭建SpringBoot底层机制开发环境1、创建Maven项目lzw-springboot2、导入相关依赖<?xmlversion="1.0"encoding="UTF-8"?><projectxmlns="http://maven.apache.o......
  • Springboot centos7 启动
     1、java-jardemo.jar说明:用这种方法启动后,不能继续执行其它命令了,如果想要继续执行其它命令,就都打断,打断一般用ctrl+c。2、java-jardemo.jar&第2种在第1种方式的基础......
  • redisson分布式限流[RRateLimiter]源码分析
    接下来在讲一讲平时用的比较多的限流模块--RRateLimiter1.简单使用publicstaticvoidmain(String[]args)throwsInterruptedException{RRateLimiterrateLimit......
  • SpringBoot3.x原生镜像-Native Image尝鲜
    前提Spring团队致力于为Spring应用程序提供原生映像支持已经有一段时间了。在SpringBoo2.x的SpringNative实验项目中酝酿了3年多之后,随着SpringFramework6和SpringBoo......
  • 多语言在线客服系统源码-自动识别中英环境-私有化部署完美支持跨境电商网站
    如果您的客户遍布全球,客户沟通就必须跨越语言障碍。用客户当地的语言跟他们交谈,可以帮助您在客户生命周期的所有阶段建立信任,当然也包括服务支持。 具体做法,看看这四点......
  • SpringBoot(三) - Ribbon客户端负载均衡,Zuul网关,Config配置中心
    1、Ribbon客户端负载均衡1.1依赖1.2配置信息#feign默认加载了ribbon负载均衡,默认负载均衡机制是:轮询#负载均衡机制是添加在消费端(客户端)的,如果改为随机,指定服务名......
  • Nginx源码编译并运行
    获取源码包并解压登录http://nginx.org/en/download.htmlwgethttp://nginx.org/download/nginx-1.20.2.tar.gztar-zxvfnginx-1.20.2.tar.gz安装Nginxcdnginx-1.2......
  • spdlog日志库源码:logger类
    目录特性类图关系logger数据成员logger函数成员构造与析构构造函数拷贝构造、移动构造交换操作log()记录日志消息格式串普通字符串日志级别宽字符支持sink_it_:将log消息交......