温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

springboot中SpringApplication的run方法

发布时间:2021-09-04 10:33:24 来源:亿速云 阅读:149 作者:chen 栏目:大数据

本篇内容介绍了“springboot中SpringApplication的run方法”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

SpringApplication的run方法解析

public ConfigurableApplicationContext run(String... args) {
    // 构造一个任务执行观察器(Java 查看时间和性能的类)
   StopWatch stopWatch = new StopWatch();
    // 开始执行,记录开始时间
   stopWatch.start();
    // 定制配置上下文,顶级父类包含Bean Factory
   ConfigurableApplicationContext context = null;
    // 定义一个错误集合(用来支持报告关于启动的错)
   Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
    //定义一个 awt 的headless(设置headless模式,名字为 java.awt.headless 的系统属性设置为true)
   configureHeadlessProperty();
    // 获取一个run监听器,主要监听SpringApplication对象,(内部只有一个EventPublishingRunListener)
   SpringApplicationRunListeners listeners = getRunListeners(args);
    //调用监听器的启动,当SpringApplication对象的run方法刚启动的时候(依靠SimpleApplicationEventMulticaster)
   listeners.starting();
   try {
        // 构造一个应用程序参数持有类  应用参数化
      ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);      
        //创建并配置Environment(该过程会获取入参、加载application配置文件),配置环境(Environment)加入到监听器对象中(SpringApplicationRunListeners)
      ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
      // 配置bean的忽略信息 扫描 pring.beaninfo.ignore 进行属性读取 可选true/false (在application文件中配置)
      configureIgnoreBeanInfo(environment);
     //打印logo 即pringboot的beaninfo.ignore样图
      Banner printedBanner = printBanner(environment);
      // 根据应用类型创建对应的Context容器 初始化bean ***
      context = createApplicationContext();
       // 从配置文件中获取具体是实现类
      exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
            new Class[] { ConfigurableApplicationContext.class }, context);
      // 刷新Context之前的准备 即准备使用上下文
      // 将SpringApplicationRunListeners、ConfigurableEnvironment、ApplicationArguments、Banner等重要组件雨上下文对象关联
      prepareContext(context, environment, listeners, applicationArguments,
            printedBanner);
      // 刷新Context容器 ***
      // 实现spring-boot-starter-*(mybatis、redis等)自动化配置的关键,包括spring.factories的加载,bean的实例化等核心工作
      refreshContext(context);
      // 刷新Context容器之后处理
      afterRefresh(context, applicationArguments);
        // 执行结束,记录执行时间
      stopWatch.stop();
      if (this.logStartupInfo) {
         new StartupInfoLogger(this.mainApplicationClass)
               .logStarted(getApplicationLog(), stopWatch);
      }
        // Context容器刷新完毕发布,这里接受ApplicationStartedEvent事件的listener会执行相应的操作
        //【Spring容器已经刷新过且应用已经启动,但是CommandLineRunners和ApplicationRunners还未调用,直接通过spring容器自己发送
        // (因为ApplicationListener已经加入spring容器)】
      listeners.started(context);
        // 触发Context容器refresh完以后的执行 唤醒运行线程
      callRunners(context, applicationArguments);
   } catch (Throwable ex) {
         // 启动错误报告处理
      handleRunFailure(context, ex, exceptionReporters, listeners);
      throw new IllegalStateException(ex);
   }
   try {
       // Context启动完毕,Runner运行完逼发布,这里接受ApplicationStartedEvent事件的listener会执行相应的操作
       //【已经调用了CommandLineRunners,直接通过spring容器自己发送(因为ApplicationListener已经加入spring容器)】
      listeners.running(context);
   } catch (Throwable ex) {
        // 启动错误报告处理
      handleRunFailure(context, ex, exceptionReporters, null);
      throw new IllegalStateException(ex);
   }
    // 返回Spring容器
   return context;
}

    返回的对象 ConfigurableApplicationContext 就是 applicationContext 子类,前者相比后者提供了更多的功能,比如实现 Lifecycle, Closeable 接口 更好的管理bean的声明周期,还有其他的 诸如:addBeanFactoryPostProcessor,setParent,setId,addApplicationListener,addProtocolResolver 等额外的功能。

  1. 创建并启动观察器

  2. 设置 java.awt.headless 系统变量

  3. 加载所有 classpath 下的 META-INF/spring.factories 中的 SpringApplicationRunListener

  4. 依次调用的 SpringApplicationRunListener 的 starting 方法,发布 springboot 启动事件

  5. 实例化 ApplicationArguments 对象 获取应用参数

  6. 创建 ConfigurableEnvironment 对象 environment

    注意 webApplicationType 控制创建的 Environment 对象的类型,当为 SERVLET 时为 StandardServletEnvironment.class,当为 REACTIVE 时为 StandardReactiveWebEnvironment.class,其余为 StandardEnvironment.class

  7. 配置 environment 对象,主要把方法参数配置到 environment 中--通过 configurePropertySources(environment, args) 设置 properties ,通过 configureProfiles(environment, args) 设置 profiles

  8. 执行所有 SpringApplicationRunListeners 的 environmentPrepared 方法发布 environmentPrepared 事件,即调用 实现ApplicationListener接口 ConfigFileApplicationListener 的 onApplicationEvent 事件 

    注意 该事件获取  EnvironmentPostProcessor类型的工厂类实例集合,并将ConfigFileApplicationListener实例追加入该集合,遍历该实例集合 一次执行postProcessEnvironment方法 分别设置 environment的propertySource属性中的systemEnvironment属性、propertySourceList属性、加载YML配置文件

  9. 即把当前的 environment 和当前的 springApplication 绑定

  10. 将 ConfigurationPropertySource 放入 environment 的 propertysource 中的第一个

  11. 打印 Banner

  12. 创建Spring容器

  13. 从配置文件中获取具体异常实现类

  14. 设置spring容器的 environment

  15. 当 beanNameGenerator 属性存在,向bean工厂中注册 beanNameGenerator; 当resourceLoader属性存在,如果 context 实现GenericApplicationContext 则把其赋值给上下文中的 resourceLoader 属性,如果 context 实现DefaultResourceLoader 则获取其加载器,赋值给上下文中的 classLoader 属性

  16. 回调 ApplicationContextInitializer 的 initialize 方法来初始化 context,其中还检测各个 ApplicationContextInitializer 是否接受该类型的容器

    注意 其在 context 中注册两个监听器‘ConditionEvaluationReportListener’和‘ServerPortInfoApplicationContextInitializer’,同时也在 context 中注册两个bean工厂后置处理器‘CachingMetadataReaderFactoryPostProcessor’和‘ConfigurationWarningsPostProcessor’

  17. 执行所有 SpringApplicationRunListener 的 contextPrepared 方法,但目前是个空实现

  18. context 中分别注册 springApplicationArguments 和 springBootBanner 这两个单例bean

  19. 获取我们的 primarySources 和 sources 加载注册到context中的 beanFactory里,即注册主类到beanFactory

  20. 执行所有 SpringApplicationRunListener 的 contextLoaded 方法,首先判断 ApplicationListener 是否属于 ApplicationContextAware,如果是的话就将spring容器赋值给该 listener,然后将该 ApplicationListener 赋值给spring容器,然后调用 ApplicationListener 的 onApplicationEvent 方法

    注意 该处向context注册了10个监听器(listeners属性的值)和一个bean工厂后置处理器‘PropertySourceOrderingPostProcessor’,并注册了一个单例bean(SpringBootloggingSystem)

  21. 调用 AbstractApplicationContext 的 refresh 方法刷新Spring容器

    设置些初始的操作(开启激活,启动日期,初始化propertySource)、配置工厂的标准上下文特征、注册 BeanPostProcessor 和 BeanFactoryPostProcessor(前者实现对bean初始化前后进行设置,后实现对 beanFactory 进行修改 或对 beanDefinition 进行修改或者增加或者初始化渴望提前初始化的 bean)、初始化国际化文件、初始化web容器、实例化非懒加载的剩余 bean 等等操作

  22. 调用 AbstractApplicationContext 的 registerShutdownHook 方法,注册一个线程该线程主要指向 doclose 方法

  23. 执行所有 SpringApplicationRunListener 的 started 方法,发布 started 事件

  24. 回调 callrunners 方法从spring容器中获取 ApplicationRunner 和 CommandLineRunner 对象,然后按照顺序排序,循环调用他们的 run 方法

  25. 执行所有 SpringApplicationRunListener 的 running 方法,发布 running 事件

  26. 第五步到二十五步执行过程中出现异常调用 handleRunFailure 方法处理不同的异常状态异常,调用 listeners.failed(context, exception),并关闭spring容器

“springboot中SpringApplication的run方法”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注亿速云网站,小编将为大家输出更多高质量的实用文章!

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI