美文网首页
spring boot 启动流程,spring boot 启动类

spring boot 启动流程,spring boot 启动类

作者: 指下光年 | 来源:发表于2021-05-29 00:47 被阅读0次

spring boot 启动类介绍

  • spring boot项目启动类代码
@SpringBootApplication
public class Application{
    public static void main(String[] args) {
      SpringApplication.run(SystemApplication.class,args);
    }
}

静态方法run(),是spring boot项目的启动入口

  • SpringBootApplication注解
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan(
  excludeFilters = {@Filter(
  type = FilterType.CUSTOM,
  classes = {TypeExcludeFilter.class}
), @Filter(
  type = FilterType.CUSTOM,
  classes = {AutoConfigurationExcludeFilter.class}
)}
)
public @interface SpringBootApplication {}
  • SpringApplication.run()
  1. @SpringBootConfiguration内部用的也是@Configuration,它是javaConfig形式的Spring Ioc容器的配置类。
  2. @EnableAutoConfiguration
@SuppressWarnings("deprecation")
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@AutoConfigurationPackage
@Import(EnableAutoConfigurationImportSelector.class)
public @interface EnableAutoConfiguration {}

借助@Import的支持,注册bean。@Import(EnableAutoConfigurationImportSelector.class)借助EnableAutoConfigurationImportSelector类,帮助springboot应用将所有符合条件的@Configuration配置都加载到Ioc容器,借助SpringFactoriesLoader工具类实现自动配置

  1. SpringFactoriesLoader其主要功能就是从指定的配置文件META-INF/spring.factories加载配置。将其中org.springframework.boot.autoconfigure.EnableutoConfiguration对应的配置项通过反射(Java Refletion)实例化为对应的标注了@Configuration的JavaConfig形式的IoC容器配置类,然后汇总为一个并加载到IoC容器。

脱离代码的演示或讲解都是流氓,上代码!!!

Spring Boot启动流程

  1. 运行springboot启动类
  2. 执行SpringApplication.run()方法
  public static ConfigurableApplicationContext run(Class<?> primarySource, String... args) {
    return run(new Class[]{primarySource}, args);
  }

  public static ConfigurableApplicationContext run(Class<?>[] primarySources, String[] args) {
    return (new SpringApplication(primarySources)).run(args);
  }
  1. SpringApplication.run()静态方法最终创建了一个SpringApplication对象,运行了其中的run方法
  2. SpringApplication的构造方法设置基础值
  public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
    this.sources = new LinkedHashSet();
    this.bannerMode = Mode.CONSOLE;
    this.logStartupInfo = true;
    this.addCommandLineProperties = true;
    this.addConversionService = true;
    this.headless = true;
    this.registerShutdownHook = true;
    this.additionalProfiles = new HashSet();
    this.isCustomEnvironment = false;
    this.lazyInitialization = false;
    //资源初始化加载器,默认null
    this.resourceLoader = resourceLoader;
    //断言主要加载资源类不能为null,否则报错
    Assert.notNull(primarySources, "PrimarySources must not be null");
    //初始化主要加载资源类集合并去重
    this.primarySources = new LinkedHashSet(Arrays.asList(primarySources));
    //判断当前WEB 应用类型,三种类型:NONE非web项目,SERVLET servlet web项目,REACTIVE 响应式web项目
    this.webApplicationType = WebApplicationType.deduceFromClasspath();
    //设置应用上下文初始化器,从"MATE-INFO/spring.factories"读取  ApplicationContextInitializer类的实例名称集合并去重,并进行set去重。(一共7个)
    this.setInitializers(this.getSpringFactoriesInstances(ApplicationContextInitializer.class));
    //设置监听器,从"META-INF/spring.factories"读取ApplicationListener类的实例名称集合并去重,并进行set去重。(一共11个)
    this.setListeners(this.getSpringFactoriesInstances(ApplicationListener.class));
    //推断主入口应用类,通过当前调用栈,获取Main方法所在类,并赋值给mainApplicationClass
    this.mainApplicationClass = this.deduceMainApplicationClass();
  }
public ConfigurableApplicationContext run(String... args) {
    //1、创建并启动计时监控类
    StopWatch stopWatch = new StopWatch();
    stopWatch.start();
    //2、初始化应用上下文和异常报告集合
    ConfigurableApplicationContext context = null;
    Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
    //3、设置系统属性“java.awt.headless”的值,默认为true,用于运行headless服务器,进行简单的图像处理,多用于在缺少显示屏、键盘或者鼠标时的系统配置,很多监控工具如jconsole 需要将该值设置为true
    configureHeadlessProperty();
    //4、创建所有spring运行监听器并发布应用启动事件,简单说的话就是获取SpringApplicationRunListener类型的实例(EventPublishingRunListener对象),并封装进SpringApplicationRunListeners对象,然后返回这个SpringApplicationRunListeners对象。说的再简单点,getRunListeners就是准备好了运行时监听器EventPublishingRunListener。
    SpringApplicationRunListeners listeners = getRunListeners(args);
    listeners.starting();
    try {
        //5、初始化默认应用参数类
        ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
        //6、根据运行监听器和应用参数来准备spring环境
        ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
        //将要忽略的bean的参数打开
        configureIgnoreBeanInfo(environment);
        //7、创建banner打印类
        Banner printedBanner = printBanner(environment);
        //8、创建应用上下文,可以理解为创建一个容器
        context = createApplicationContext();
        //9、准备异常报告器,用来支持报告关于启动的错误
        exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
                    new Class[] { ConfigurableApplicationContext.class }, context);
        //10、准备应用上下文,该步骤包含一个非常关键的操作,将启动类注入容器,为后续开启自动化提供基础
        prepareContext(context, environment, listeners, applicationArguments, printedBanner);
        //11、刷新应用上下文
        refreshContext(context);
        //12、应用上下文刷新后置处理,做一些扩展功能
        afterRefresh(context, applicationArguments);
        //13、停止计时监控类
        stopWatch.stop();
        //14、输出日志记录执行主类名、时间信息
        if (this.logStartupInfo) {
                new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
        }
        //15、发布应用上下文启动监听事件
        listeners.started(context);
        //16、执行所有的Runner运行器
        callRunners(context, applicationArguments);
    }catch (Throwable ex) {
        handleRunFailure(context, ex, exceptionReporters, listeners);
        throw new IllegalStateException(ex);
    }
    try {
        //17、发布应用上下文就绪事件
        listeners.running(context);
    }catch (Throwable ex) {
        handleRunFailure(context, ex, exceptionReporters, null);
        throw new IllegalStateException(ex);
    }
    //18、返回应用上下文
    return context;
}

相关文章

网友评论

      本文标题:spring boot 启动流程,spring boot 启动类

      本文链接:https://www.haomeiwen.com/subject/kpussltx.html