Spring Boot 源码分析 - 运行过程

执行入口 类 采用静态方法调用

SpringApplication.run(XXXApplication.class,args);

进入 SpringApplication

run(XXXApplication.class,args)

public static ConfigurableApplicationContext run(Class<?> primarySource,
      String... args) {
   return run(new Class<?>[] { primarySource }, args);
}

primarySource : 应用运行类 , 方法调用 内部 run 方法重载的 方法

最终 通过有参构造方法实例化 SpringApplication 对象,并调用 run 方法

public static ConfigurableApplicationContext run(Class<?>[] primarySources,
      String[] args) {
   return new SpringApplication(primarySources).run(args);
}

该方法有两个 部分功能调用

new SpringApplication(primarySources)

这部分主要 有四部分功能

  1. 推断当前应用程序运行类型,并赋值给 webApplicationType 属性
  2. 加载项目jar类路径中的文件中 META-INF/spring.factories 中 包含ApplicationContextInitializer 的实现类 并实例化成对象,并存储到 initializers 数组属性中
  3. 加载项目jar类路径中的文件中 META-INF/spring.factories 中 包含ApplicationListener 的实现类 并实例化成对象,并存储到 initializers 数组属性中
  4. 推断当前应用程序main运行主类,并赋值给 mainApplicationClass 属性
public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
   this.resourceLoader = resourceLoader;
   Assert.notNull(primarySources, "PrimarySources must not be null");
   this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
   this.webApplicationType = WebApplicationType.deduceFromClasspath();
   setInitializers((Collection) getSpringFactoriesInstances(
         ApplicationContextInitializer.class));
   setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
   this.mainApplicationClass = deduceMainApplicationClass();
}

getSpringFactoriesInstances

该方法 主要有二部分功能

  1. loadFactoryNames spring.factories文件加载 匹配 type 的类名称集合
  2. createSpringFactoriesInstances 根据 类名称集合 ,根据 构造函数反射 实例化类对象
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type,
      Class<?>[] parameterTypes, Object... args) {
   ClassLoader classLoader = getClassLoader();
   // Use names and ensure unique to protect against duplicates
   Set<String> names = new LinkedHashSet<>(
         SpringFactoriesLoader.loadFactoryNames(type, classLoader));
   List<T> instances = createSpringFactoriesInstances(type, parameterTypes,
         classLoader, args, names);
   AnnotationAwareOrderComparator.sort(instances);
   return instances;
}

run(args)

  1. 配置 并准备 程序运行环境 
  2. 打印启动横幅
  3. 创建应用程序上下文 createApplicationContext();
     通过 webApplicationType 属性 实例化需要加载的 应用程序上下文类对象
  4. 配置程序运行环境

    configureHeadlessProperty(); Java 的Headless模式,Headless模式是在缺少显示屏、键盘或者鼠标是的系统配置

    getRunListeners(args); 获取程序运行监听器 加载项目jar类路径中的文件中 META-INF/spring.factories 中 包含SpringApplicationRunListener 的实现类 并实例化成对象,并存储到 initializers 数组属性中

    prepareEnvironment(listeners, applicationArguments); 配置 环境变量 ,通过 执行SpringApplicationRunListener environmentPrepared 事件, 加载 并实例化 META-INF/spring.factories EnvironmentPostProcessor PropertySourceLoader 接口实现类configureIgnoreBeanInfo(environment); 配置 需要忽略的bean 信息

  5. 加载并实例化 Spring Boot异常报告器
         获取程序运行监听器 加载项目jar类路径中的文件中 META-INF/spring.factories 中 包含SpringBootExceptionReporter的实现类 并实例化成对象,并存储到 initializers 数组属性中
  6. 准备应用程序上下文

    配置应用程序上下文环境

    配置后处理上下文 :注册内部配置Bean名称生成器 ,处理@Configuration 自定义名称;设置程序转换服务提供程序各类转换处理

    执行 ApplicationContextInitializer 的实现类 的初始化方法 initialize(context)

    添加 springApplicationArguments springBootBanner 单例到 bean 工厂ConfigurableListableBeanFactory

    加载bean 定义信息类 比如 解析@bean 注解的bean 、xml 配置bean 的定义读取类 ,先读取 启动类

  7. 刷新加载应用程序上下文
  8. 暴露提供子类实现类 在上下文刷新完成后进行干预操作 afterRefresh(context, applicationArguments);

          提供 在上下文刷新 完 ,执行 某些操作 callRunners(context, applicationArguments); 提供 ApplicationRunner ApplicationRunner.class 、CommandLineRunner.class 两个功能函数类接口 (JDK 8)

public ConfigurableApplicationContext run(String... args) {
   StopWatch stopWatch = new StopWatch();
   stopWatch.start();
   ConfigurableApplicationContext context = null;
   Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
   configureHeadlessProperty();
   SpringApplicationRunListeners listeners = getRunListeners(args);
   listeners.starting();
   try {
      ApplicationArguments applicationArguments = new DefaultApplicationArguments(
            args);
      ConfigurableEnvironment environment = prepareEnvironment(listeners,
            applicationArguments);
      configureIgnoreBeanInfo(environment);
      Banner printedBanner = printBanner(environment);
      context = createApplicationContext();
      exceptionReporters = getSpringFactoriesInstances(
            SpringBootExceptionReporter.class,
            new Class[] { ConfigurableApplicationContext.class }, context);
      prepareContext(context, environment, listeners, applicationArguments,
            printedBanner);
      refreshContext(context);
      afterRefresh(context, applicationArguments);
      stopWatch.stop();
      if (this.logStartupInfo) {
         new StartupInfoLogger(this.mainApplicationClass)
               .logStarted(getApplicationLog(), stopWatch);
      }
      listeners.started(context);
      callRunners(context, applicationArguments);
   }
   catch (Throwable ex) {
      handleRunFailure(context, ex, exceptionReporters, listeners);
      throw new IllegalStateException(ex);
   }

   try {
      listeners.running(context);
   }
   catch (Throwable ex) {
      handleRunFailure(context, ex, exceptionReporters, null);
      throw new IllegalStateException(ex);
   }
   return context;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值