SpringBoot 从入门到光头 第十章 原理解析


SpringBoot 从入门到光头 —— 第十章 原理解析


1. SpringBoot 原理

Spring 原理、Spring 注解、SpringMVC 原理、自动配置原理、SpringBoot 原理

2. SpringBoot 自动过程

  • 创建 SpringApplication

    • 保存一些信息
    • 判定当前应用的类型 ClassUtils,一般情况下是 Servlet
    • bootstrappers初始启动引导器(List<Bootstrapper>):去spring.factories 文件中查找 org.springframework.boot.Bootstrapper
    • 查找 ApplicationContextInitializerspring.factories 中查找 ApplicationContextInitializer
      • List<ApplicationContextInitializer<?>> initializers
    • 查找 ApplicationListener应用监听器,去 spring.factories 中查找 ApplicationListener
      • List<ApplicationListener<?>> listeners
  • 运行 SpringApplication

    • StopWatch

    • 记录应用的启动时间

    • 创建引导上下文(Context 环境)createBootstrapContext()

      org.springframework.boot.BootstrapRegistryInitializer

      /**
       * Callback interface that can be used to initialize a &#123;@link BootstrapRegistry&#125; before it
       * is used.
       *
       * @author Phillip Webb
       * @since 2.4.5
       * @see SpringApplication#addBootstrapRegistryInitializer(BootstrapRegistryInitializer)
       * @see BootstrapRegistry
       */
      @FunctionalInterface
      public interface BootstrapRegistryInitializer &#123;
          /**
           * Initialize the given &#123;@link BootstrapRegistry&#125; with any required registrations.
           * @param registry the registry to initialize
           */
          void initialize(BootstrapRegistry registry);
      &#125;
      
      • 获取到所有之前的 bootstrappers 挨个执行 intitialize() 方法来完成对引导启动器上下文环境设置
    • 让当前应用进入 headless 模式,java.awt.headless

    • 获取所有 RunListener(运行监听器)【为了方便所有 Listener 进行事件感知】

      • getSpringFactoriesInstancesspring.factoriesSpringApplicationRunListener

        SpringApplicationRunListener
    • 遍历 SpringApplicationRunListener 调用 starting 方法

      • 相当于通知所有感兴趣系统正在启动过程的人,项目正在 starting
    • 保存命令行参数 ApplicationArguments

    • 准备环境 prepareEnvironment()

      • 返回或者创建基础环境信息对象,StandardServletEnvironment
      • 配置环境信息对象
        • 读取所有的配置源的配置属性值
      • 绑定环境信息
      • 监听器调用 listener.environmentPrepared(),通知所有的监听器当前环境准备完成
    • 创建 IOC 容器(createApplicationContext()

      • 根据项目类型(Servlet)创建容器
      • 在当前会话中创建 AnnotationConfigServletWebServerApplicationContext
    • 准备 ApplicationContext IOC 容器的基本信息 prepareContext()

      • 保存环境信息

      • IOC 容器的后置处理流程

      • 应用初始化器:applyInitializers

        • 遍历所有的 ApplicationContextInitializer 调用 initialize() 来对 IOC 容器进行初始化扩展功能

          GetInitializers

        • 遍历所有的 Listener 调用 contextPrepared()EventPublishRunListenr,通知所有的监听器 contextPrepared()

      • 所有的监听器调用 contextLoaded() 通知所有的监听器 contextLoaded()

    • 刷新 IOC 容器 refreshContext()

      • 创建容器中的所有组件(Spring 注解)
    • 容器刷新完成后的工作:afterRefresh()

    • 所有监听器调用 listeners.started(context),通知所有的监听器 started

    • 调用所有 runnerscallRunners()

        • 获取容器中的 ApplicationRunner
          • 获取容器中的 CommandLineRunner
        • 合并所有 runner 并且按照 @Order 进行排序

          • 遍历所有的 runner,调用 run() 方法

            org.springframework.boot.ApplicationRunner

            /**
             * Interface used to indicate that a bean should <em>run</em> when it is contained within
             * a &#123;@link SpringApplication&#125;. Multiple &#123;@link ApplicationRunner&#125; beans can be defined
             * within the same application context and can be ordered using the &#123;@link Ordered&#125;
             * interface or &#123;@link Order @Order&#125; annotation.
             *
             * @author Phillip Webb
             * @since 1.3.0
             * @see CommandLineRunner
             */
            @FunctionalInterface
            public interface ApplicationRunner &#123;
                /**
                 * Callback used to run the bean.
                 * @param args incoming application arguments
                 * @throws Exception on error
                 */
                void run(ApplicationArguments args) throws Exception;
            &#125;
            

            org.springframework.boot.CommandLineRunner

            /**
             * Interface used to indicate that a bean should <em>run</em> when it is contained within
             * a &#123;@link SpringApplication&#125;. Multiple &#123;@link CommandLineRunner&#125; beans can be defined
             * within the same application context and can be ordered using the &#123;@link Ordered&#125;
             * interface or &#123;@link Order @Order&#125; annotation.
             * <p>
             * If you need access to &#123;@link ApplicationArguments&#125; instead of the raw String array
             * consider using &#123;@link ApplicationRunner&#125;.
             *
             * @author Dave Syer
             * @since 1.0.0
             * @see ApplicationRunner
             */
            @FunctionalInterface
            public interface CommandLineRunner &#123;
                /**
                 * Callback used to run the bean.
                 * @param args incoming main method arguments
                 * @throws Exception on error
                 */
                void run(String... args) throws Exception;
            &#125;
            
    • 如果以上有异常:

      • 调用 Listener 的 failed() 方法
    • 调用所有监听器的 running() 方法 listeners.running(context),通知所有的监听器 running

    • running() 如果有问题,继续通知 failed,调用所有 Listener 的 failed() 方法,通知所有的监听器 failed

3. Application Events 和 Liateners

https://docs.spring.io/spring-boot/docs/current/reference/html/spring-boot-features.html#boot-features-application-events-and-listeners

  • ApplicationContextInitializer
  • ApplicationListener
  • SpringAppliactionRunListener

示例代码:

com.gregperlinli.boot.listener.MyApplicationContextInitializer

/**
 * @author gregPerlinLi
 * @since 2021-11-29
 */
public class MyApplicationContextInitializer implements ApplicationContextInitializer &#123;
    @Override
    public void initialize(ConfigurableApplicationContext applicationContext) &#123;
        System.out.println("MyApplicationContextInitializer.initialize ... ");
    &#125;
&#125;

com.gregperlinli.boot.listener.MyApplicationListener

/**
 * @author gregPerlinLi
 * @since 2021-11-29
 */
public class MyApplicationListener implements ApplicationListener &#123;
    @Override
    public void onApplicationEvent(ApplicationEvent event) &#123;
        System.out.println("MyApplicationListener.onApplicationEvent ... ");
    &#125;
&#125;

com.gregperlinli.boot.listener.MySpringApplicationRunListener

/**
 * @author gregPerlinLi
 * @since 2021-11-29
 */
public class MySpringApplicationRunListener implements SpringApplicationRunListener &#123;
    private SpringApplication application;
  
    public MySpringApplicationRunListener(SpringApplication application, String[] args) &#123;
        this.application = application;
    &#125;
    @Override
    public void starting(ConfigurableBootstrapContext bootstrapContext) &#123;
        System.out.println("MySpringApplicationRunListener.starting ... ");
    &#125;
    @Override
    public void environmentPrepared(ConfigurableBootstrapContext bootstrapContext, ConfigurableEnvironment environment) &#123;
        System.out.println("MySpringApplicationRunListener.environmentPrepared ... ");
    &#125;
    @Override
    public void contextPrepared(ConfigurableApplicationContext context) &#123;
        System.out.println("MySpringApplicationRunListener.contextPrepared ... ");
    &#125;
    @Override
    public void contextLoaded(ConfigurableApplicationContext context) &#123;
        System.out.println("MySpringApplicationRunListener.contextLoaded ... ");
    &#125;
    @Override
    public void started(ConfigurableApplicationContext context, Duration timeTaken) &#123;
        System.out.println("MySpringApplicationRunListener.started ... ");
    &#125;
    @Override
    public void ready(ConfigurableApplicationContext context, Duration timeTaken) &#123;
        System.out.println("MySpringApplicationRunListener.ready ... ");
    &#125;
    @Override
    public void failed(ConfigurableApplicationContext context, Throwable exception) &#123;
        System.out.println("MySpringApplicationRunListener.failed ... ");
    &#125;
&#125;

spring.factories

org.springframework.context.ApplicationContextInitializer=\
  com.gregperlinli.boot.listener.MyApplicationContextInitializer

org.springframework.context.ApplicationListener=\
  com.gregperlinli.boot.listener.MyApplicationListener

org.springframework.boot.SpringApplicationRunListener=\
  com.gregperlinli.boot.listener.MySpringApplicationRunListener

4. ApplicationRunnerCommandLineRunner

示例代码:

com.gregperlinli.boot.listener.MyApplicationRunner

/**
 * @author gregPerlinLi
 * @since 2021-11-29
 */
@Order(1)
@Component
public class MyApplicationRunner implements ApplicationRunner &#123;
    @Override
    public void run(ApplicationArguments args) throws Exception &#123;
        System.out.println("MyApplicationRunner.run ... ");
    &#125;
&#125;

com.gregperlinli.boot.listener.MyCommandLineRunner

/**
 * Application startup does a one-time thing
 *
 * @author gregPerlinLi
 * @since 2021-11-29
 */
@Order(2)
@Component
public class MyCommandLineRunner implements CommandLineRunner &#123;
    @Override
    public void run(String... args) throws Exception &#123;
        System.out.println("MyCommandLineRunner.run ... ");
    &#125;
&#125;


文章作者: gregPerlinLi
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 gregPerlinLi !
  目录