SpringBoot一些重要知识点速记

408 阅读5分钟

这是我参与11月更文挑战的第5天,活动详情查看:2021最后一次更文挑战

  • SpringBoot整合tomcat原理(很简单,没那么复杂)

    • SpringBoot项目在启动的时候,如果发现当前项目是一个web项目(引入了web依赖)。那么就会创建一个web版的IOC容器ServletWebServerApplicationContext。

    • 在该IOC容器加载的时候会去寻找 ServletWebServerFactory的实现bean。

    • 而我们自动配置中会自动配置一个ServletWebServerFactoryAutoConfiguration(Servlet工厂的自动配置类),这个自动配置会依据我们的依赖加载对应的ServletWebServerFactory工厂实现。

    • 然后通过这个SerlvetWebServer工厂来创建tomcat服务器并启动。(tomcat的源码是被打包成依赖加载进项目了,我们可以通过new Tomcat()来创建Tomcat服务器,并start()启动它。不是外部启动,而是通过代码的方式启动)。

  • 零配置原理

    • 这个零配置最大的体现其实还是在tomcat和spring mvc的配置上实现了零配置。(可以看spring mvc那节)
  • 自动装配的原理

    • 在SpringBoot启动类上面有一个注解@ SpringBootApplication。这是一个组合注解,该注解组合了一个EnableAutoConfiguration注解。依据名字可以知道,这个就是开启自动配置的。

    • EnableAutoConfiguration的作用就是import一个AutoConfigurationImportSelector类(所有的EnableXXX的作用基本都是这个)。这个select的主要作用就是返回一堆的全限定类名,Spring会将这些类全部加载进IOC容器。

    • 该Selector类里面会通过SpringFactoriesLoader去加载所有jar包中存在META-INF/spring.factories文件的配置中key为org.springframework.boot.autoconfigure.EnableAutoConfiguration的自动配置类配置。(类似于JavaSPI机制,但是并不是哦)。

    • 而我们spring-boot-autoconfigure模块中,有该配置文件,里面已经预定义好了100多条自动配置类。

    • 这些自动配置类并不会全部加载,而是按需加载。

      • 首先会过滤一波配置类,比如我们在SpringBootApplication注解上标注了要被排除的注解类。

      • 通过如@ ConditionalClass的Conditional注解,会判断我们当前项目中是否有自动配置需要的依赖类。(我们一般结合对应的starter来导入这些类,并完成自动配置。)

    • 后面这些配置类就会被加载并解析,将需要配置的bean都加载到Spring容器中。

  • 如何自定义starter以及原理

    • 对于那些大概率会被多个项目引用的,我们希望能够在开发中快速集成的模块,十分建议将其封装为starter

    • starter有下面几个核心组成

      1. 编写@ ConfigurationProperties配置类,约定项目需要的配置。

      2. 编写自动配置类,依据配置类的信息,来指定需要创建什么样的bean。这里面就只需要注意下用@ Conditional注解来条件注入配置类。

      3. META-INF/spring.factories 下配置org.springframework.boot.autoconfigure.EnableAutoConfiguration,指定需要加载的自动配置类。

  • springboot启动流程

    • main方法会调用SpringApplication.run方法。该方法就是NEW创建一个SpringApplication对象。然后运行SpringApplication对象的run方法。

    • 创建SpringApplication对象(new SpringApplication)

      • 判断当前项目的类型是web还是非web的

      • 去spring.factories找 ApplicationContextInitializer

      • 去spring.factories找 ApplicationListener

      • 这块主要目的就是判断当前项目类型,并找出所有spring.factories下面的ApplicationContextInitializer和ApplicationListener

    • 运行SpringApplication对象(.run(args))

      • 获取所有 RunListener,从所有的spring.factories找 SpringApplicationRunListener,并调用starting方法,通知对项目启动感兴趣的监听器,项目在启动中。

      • 初始化Environment环境,web会创建StandardServletEnvironment环境对象。环境准备好了,会通知所有监听器环境准备完成。

      • createApplicationContext创建IOC容器,依据web还是其他的什么项目创建对应的IOC容器(一共三种,web的,正常的,reactive的)。

      • prepareContext

        • IOC容器的后置处理流程

        • 调用所有的ApplicationContextInitializer的initialize方法,对ioc容器进行初始化扩展功能。

        • 通知所有的监听器contextPrepared事件

        • 通知所有的监听器contextLoad事件

      • refreshContext

        • 开始正式刷新IOC容器,调用容器的refresh方法。

        • refresh方法调用到onRefresh方法的时候,在onRefresh方法执行完会调用createWebServer去容器拿到ServletWebServerFactory的实现类bean(自动配置进去的)然后来创建tomcat并启动

        • 启动tomcat会自动回调ServletContainerInitializer接口实现类,从而将DIspatcherServlet这些都注入进去。

        • 总结就是先初始化IOC容器,然后再onRefresh结束后,会启动tomcat并初始化SpringMVC相关的东西。

      • afterRefresh

        • 什么都没做
      • listeners.started(context); 通知所有listener,started事件

      • callRunners 调用所有的runner类,执行他们的run方法。(就是CommandLineRunner和ApplicationRunner的实现)

      • listeners.running 通知监听器,boot项目正在运行中。

    • 整个SpringBoot启动流程,无非就是IOC的启动流程中扩展了一些事件监听机制。以及在onRefresh方法后tomcat做初始化启动工作。

  • SpringBoot的一些扩展点

    • SpringApplicationRunListener

      • Spring Boot启动过程中各个环节可以监听或者发布一些事件。
    • ApplicationListener

      • @ EventListener注解可以监听SpringBoot项目内部的事件。
    • ApplicationContextInitializer

      • 在ConfigurableApplicationContext这类型容器的refresh执行前可以做一些处理。
    • CommandLineRunner和ApplicationRunner

      • 即在springboot项目启动后需要做一些什么事情。
  • 不想用tomcat想用其他的怎么做?

    • springboot提供了三种容器:tomcat , jetty, undertow

    • springboot默认是tomcat作为servlet容器的,这是因为spring-boot-starter-web中默认依赖是tomcat,所以自动配置的时候,只会配置tomcat的servlet容器

    • 如果想要换就需要在项目中先将tomcat的依赖移除掉,然后添加自己想要的容器的starter依赖。比如jetty的。

  • springboot的原理

    • 就是springboot的启动原理