ylcc-zyq

一、启动流程

1.创建SpringApplication对象

//通过调用自身的构造方法创建对象
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources){
    this.resourceLoader = resourceLoader;
    Assert.notNull(primarySources, "PrimarySources must not be null");
    //保存配置类
    this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
    //当前web应用的类型
    this.webApplicationType = WebApplicationType.deduceFromClasspath();
    //从类路径下找到META-INF/spring.factories配置的所有ApplicationContextInitializer;并保存起来
    setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
    //从类路径下找到META-INF/spring.factories配置的所有ApplicationListener;并保存起来
    setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
    //从多个配置类中找到有main方法的配置类
    this.mainApplicationClass = deduceMainApplicationClass();
}

2.运行run方法

public ConfigurableApplicationContext run(String... args) {
   StopWatch stopWatch = new StopWatch();
   stopWatch.start();
   ConfigurableApplicationContext context = null;
   Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
    //awt相关配置
   configureHeadlessProperty();
    //获取SpringApplicationRunListeners:从类路径下找到META-INF/spring.factories配置的所有SpringApplicationRunListener
   SpringApplicationRunListeners listeners = getRunListeners(args);
   //回调所有的SpringApplicationRunListener的starting方法
    listeners.starting();
   try {
       //封装命令行参数
      ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
      //准备并配置环境,创建环境完成后回调所有SpringApplicationRunListener的environmentPrepared方法
       ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
       //配置忽略bean信息
      configureIgnoreBeanInfo(environment);
       //在控制台打印图案
      Banner printedBanner = printBanner(environment);
       //创建applicationContext。根据当前环境类型,来判断创建ioc容器的类型是普通的ioc还是web的ioc,通过反射完成创建
      context = createApplicationContext();
       //出现异常后做异常分析报告
      exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
            new Class[] { ConfigurableApplicationContext.class }, context);
       //准备上下文环境,将environment保存到ioc中
       //调用applyInitializers(context),回调所有ApplicationContextInitializer的initialize方法
       //调用listeners.contextPrepared(context);,回调所有SpringApplicationRunListener的contextPrepared方法
       //最后调用listeners.contextLoaded(context);,回调所有SpringApplicationRunListener的contextLoaded方法
      prepareContext(context, environment, listeners, applicationArguments, printedBanner);
      //刷新容器,ioc容器初始化完成。
       //扫描,创建,加载所有组件的地方
       refreshContext(context);
       //2.x版本为空方法
      afterRefresh(context, applicationArguments);
      stopWatch.stop();
       //打印启动日志
      if (this.logStartupInfo) {
         new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
      }
       //回调所有ApplicationListener的started方法
      listeners.started(context);
       //从ioc容器中获取所有的ApplicationRunner和CommandLineRunner并回调,ApplicationRunner先回调,CommandLineRunner后回调
      callRunners(context, applicationArguments);
   }
   catch (Throwable ex) {
      handleRunFailure(context, ex, exceptionReporters, listeners);
      throw new IllegalStateException(ex);
   }

   try {
       //回调所有SpringApplicationRunListener的running方法
      listeners.running(context);
   }
   catch (Throwable ex) {
      handleRunFailure(context, ex, exceptionReporters, null);
      throw new IllegalStateException(ex);
   }
    //启动完成后返回ioc容器
   return context;
}

3. 事件监听机制

由上面可知,在启动过程中,存在的几个事件回调机制

  1. ApplicationContextInitializer:在准备上下文环境的时候会调用该接口实现类的initialize方法。通常在需要对应用程序上下文进行一些程序初始化的Web应用程序中使用。

  2. SpringApplicationRunListener:监听SpringApplication调用run方法中执行的一些关键方法

  3. ApplicationRunner:实现了该接口的类,会在启动过程中调用类的run方法

  4. CommandLineRunner:与ApplicationRunner基本相同,但后于ApplicationRunner调用run方法。

配置

ApplicationContextInitializer与SpringApplicationRunListener需要在META-INF/spring.factories中进行配置

ApplicationRunner与CommandLineRunner只需要加入到IOC容器中便可

二、自定义starter

1.如何编写自动配置?我们可以先看看一些自动配置类都用了什么

@Configuration  //指定这个类是配置类
@ConditionalOnXXX //在指定条件成立的情况下自动配置类生效
@AutoConfigureAfter  //指定自动配置类的顺序
@Bean //给容器中添加组件

@ConfigurationProperties//结合相关xxxProperties类来绑定相关的配置
@EnableConfigurationProperties //让xxxProperties生效加入到容器中

要想 自动配置类能够在启动的时候就加载。将其配置在META-INF/spring.factories中

例:

# Auto Configure
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
org.springframework.boot.autoconfigure.admin.SpringApplicationAdminJmxAutoConfiguration,\
org.springframework.boot.autoconfigure.aop.AopAutoConfiguration,\

其中第一行是接口,\代表换行,其后跟着的是配置类

2.模式

启动器只用来做依赖导入

专门写一个自动配置类

启动器依赖自动配置;使用只需引入启动器(starter)

过程如下:

  1. 创建两个项目,一个maven项目,一个springboot项目
  2. maven项目中什么都不写,单纯地添加另一个项目的坐标。这个maven项目就作为启动器,在添加启动器的依赖的时候,就会将自动配置类也添加进来。
  3. 在springboot项目中,创建一个类xxxProperties使用@ConfigurationProperties注解,来绑定相关的配置属性。
  4. 使用@Configuration 创建一个配置类,@EnableConfigurationProperties(xxxProperties.class)。可根据需求添加注解,在配置类中添加组件。
  5. 将配置类在META-INF/spring.factories中进行配置

分类:

技术点:

相关文章: