• SpringBoot流程解析(二)


    目录

    SpringApplication::run

    十一

    十二

    十三

    十四

    十五

    十六

    十七

    十八


    上篇分析完启动类注解和SpringApplication构造函数。

    SpringApplication::run

    启动一个spring应用,创建并刷新一个新的ApplicationContext

    1. public ConfigurableApplicationContext run(String... args) {
    2. StopWatch stopWatch = new StopWatch();
    3. // 一
    4. stopWatch.start();
    5. // 二
    6. ConfigurableApplicationContext context = null;
    7. // 三
    8. Collection exceptionReporters = new ArrayList<>();
    9. // 四
    10. configureHeadlessProperty();
    11. // 五
    12. SpringApplicationRunListeners listeners = getRunListeners(args);
    13. // 六
    14. listeners.starting();
    15. try {
    16. // 七
    17. ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
    18. // 八
    19. ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
    20. // 九
    21. configureIgnoreBeanInfo(environment);
    22. // 十
    23. Banner printedBanner = printBanner(environment);
    24. // 十一
    25. context = createApplicationContext();
    26. // 十二
    27. exceptionReporters = getSpringFactoriesInstances(SpringBootExceptionReporter.class,
    28. new Class[] { ConfigurableApplicationContext.class }, context);
    29. // 十三
    30. prepareContext(context, environment, listeners, applicationArguments, printedBanner);
    31. // 十四
    32. refreshContext(context);
    33. // 十五
    34. afterRefresh(context, applicationArguments);
    35. stopWatch.stop();
    36. if (this.logStartupInfo) {
    37. new StartupInfoLogger(this.mainApplicationClass).logStarted(getApplicationLog(), stopWatch);
    38. }
    39. // 十六
    40. listeners.started(context);
    41. // 十七
    42. callRunners(context, applicationArguments);
    43. }
    44. catch (Throwable ex) {
    45. handleRunFailure(context, ex, exceptionReporters, listeners);
    46. throw new IllegalStateException(ex);
    47. }
    48. try {
    49. // 十八
    50. listeners.running(context);
    51. }
    52. catch (Throwable ex) {
    53. handleRunFailure(context, ex, exceptionReporters, null);
    54. throw new IllegalStateException(ex);
    55. }
    56. return context;
    57. }

    是一个计时器工具类,这里先记录了项目的启动时间

    初始化应用上下文

    初始化异常报告器

    设置java.awt.headless为true

    为true的话是告知系统不要指望显示器、鼠标、键盘等可以正常运行,这是一个服务端程序,用到这些外设的时候需要靠自己模拟

    我们点进来看

    1. private SpringApplicationRunListeners getRunListeners(String[] args) {
    2. Class[] types = new Class[] { SpringApplication.class, String[].class };
    3. return new SpringApplicationRunListeners(logger,
    4. getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args));
    5. }

    我们又看到了getSpringFactoriesInstances这个方法(不记得的可以返回SpringBoot流程解析(一)去回顾),它把SpringApplicationRunListener作为key,取到的value是org.springframework.boot.context.event.EventPublishingRunListener(从spring.factories取得)。最后放入集合返回。

    点进去

    1. public void starting() {
    2. this.initialMulticaster.multicastEvent(new ApplicationStartingEvent(this.application, this.args));
    3. }

     先看initialMulticaster

    在初始化EventPublishingRunListener时初始化了initialMulticaster

    public EventPublishingRunListener(SpringApplication application, String[] args) {
       this.application = application;
       this.args = args;
       this.initialMulticaster = new SimpleApplicationEventMulticaster();
       for (ApplicationListener listener : application.getListeners()) {
          this.initialMulticaster.addApplicationListener(listener);
       }
    }

     再看new ApplicationStartingEvent(this.application, this.args)

    构建了一个ApplicationStartingEvent

    public EventObject(Object source) {
        if (source == null)
            throw new IllegalArgumentException("null source");
    
        this.source = source;
    }

     最后看multicastEvent

    先根据事件类型获取到合适的监听器,然后对这些合适的监听器遍历,每一个监听器都开启一个独立的线程去执行监听

    public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
       ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
       Executor executor = getTaskExecutor();
       for (ApplicationListener listener : getApplicationListeners(event, type)) {
          if (executor != null) {
             executor.execute(() -> invokeListener(listener, event));
          }
          else {
             invokeListener(listener, event);
          }
       }
    }

    解析启动入参

    解析配置环境,如配置文件、系统变量等并通过监听器广播环境变量准备完毕事件

    默认设置spring.beaninfo.ignore系统属性为true。

    保证某些bean不会添加到准备的环境中。

    打印banner

    十一

    根据webApplicationType初始化spring上下文

    十二

    初始化配置的异常报告类

    十三

    准备上下文

    主要分为6个步骤。

    • setEnvironment:设置上下文环境
    • postProcessApplicationContext:上下文后置处理,默认没做什么事。
    • applyInitializers:调用之前实例化的几个ApplicationContextInitializer类的initialize方法
    • contextPrepared:向listeners发送上下文已准备完毕的通知。
    • load:BeanDefinitionLoader可以加载各种bean,比如注解、XML、package等多种类型的bean,在后面利用BeanDefinitionLoader将这些beans都加载进上下文中。
    • contextLoaded:向listeners发送上下文已加载完毕的通知。

    十四

    刷新上下文(属于spring知识)

    十五

    空实现,自己可以自定义实现

    十六

    发布启动完成事件

    十七

    如果有ApplicationRunner或者CommandLineRunner类型的bean,则触发run函数,启动任务。

    十八

    监听应用上下文运行

  • 相关阅读:
    流式DMA映射实践3:dmaengine与memcpy
    使用jdbc技术连接数据库
    DDoS攻击和CC攻击
    设计模式之美——实战MVC的意义
    RabbitMQ--基础--04--运转流程
    一次性解决office部署问题(即点即用等)
    分式理想 & 对偶群 & 对偶空间
    MySQL基础练习,涉及建库、见表、约束、修改表结构等,超详细
    LAS Spark+云原生:数据分析全新解决方案
    猿创征文| 内网穿透工具(全免费)
  • 原文地址:https://blog.csdn.net/wai_58934/article/details/126558544