• SpringBoot源码学习(二) 发布启动事件


    运行Spring应用程序

    public ConfigurableApplicationContext run(String... args) {
       StopWatch stopWatch = new StopWatch();
       stopWatch.start();
       ConfigurableApplicationContext context = null;
       Collection<SpringBootExceptionReporter> exceptionReporters = new ArrayList<>();
       // 配置无头属性, 设置该应用程序即使没有检测到显示器也允许启动
       configureHeadlessProperty();
       // 从`META-INF/spring.factories`文件集中获取SpringApplicationRunListener的子类listener
       SpringApplicationRunListeners listeners = getRunListeners(args);
       // 开启事件监听,通知监听者们(listener)执行相应操作
       listeners.starting();
       try {
          // 封装命令行参数
          ApplicationArguments applicationArguments = new DefaultApplicationArguments(args);
          // 准备环境
          ConfigurableEnvironment environment = prepareEnvironment(listeners, applicationArguments);
          // 配置忽略信息
          configureIgnoreBeanInfo(environment);
          // 打印banner
          Banner printedBanner = printBanner(environment);
          // 创建应用上下文
          context = createApplicationContext();
          // 从`META-INF/spring.factories`文件集中获取SpringBootExceptionReporter的子类
          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;
    }
    

    获取监听器

    调用getRunListeners(args)方法,实例化一个SpringApplicationRunListeners对象。 通过getSpringFactoriesInstances方法读取META-INF/spring.factories进而实例化EventPublishingRunListener

    /**
     * 从`META-INF/spring.factories`文件集中获取SpringApplicationRunListener的子类listener
     * @param args 命令行参数
     * @return
     */
    private SpringApplicationRunListeners getRunListeners(String[] args) {
       Class<?>[] types = new Class<?>[] { SpringApplication.class, String[].class };
       // 实例化观察模式的目标类, 在实例化时绑定监听器(SpringApplicationRunListener子类)
       return new SpringApplicationRunListeners(logger,
             getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args));
    }
    
    org.springframework.boot.SpringApplicationRunListener=
    org.springframework.boot.context.event.EventPublishingRunListener
    

    注意: getSpringFactoriesInstances参数中的this,此方法将SpringApplication本身也传递过去了。

    EventPublishingRunListener初始化

    private <T> List<T> createSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes,
          ClassLoader classLoader, Object[] args, Set<String> names) {
       List<T> instances = new ArrayList<>(names.size());
       // 此时`names`只有`org.springframework.boot.context.event.EventPublishingRunListener`一个元素
       for (String name : names) {
          try {
             Class<?> instanceClass = ClassUtils.forName(name, classLoader);
             Assert.isAssignable(type, instanceClass);
             // 行参parameterTypes此时为`new Class<?>[] { SpringApplication.class, String[].class }`
             Constructor<?> constructor = instanceClass.getDeclaredConstructor(parameterTypes);
             // 实参此时为 `this, args`,this为SpringApplication实例, args为命令行参数
             T instance = (T) BeanUtils.instantiateClass(constructor, args);
             instances.add(instance);
          }
          catch (Throwable ex) {
             throw new IllegalArgumentException("Cannot instantiate " + type + " : " + name, ex);
          }
       }
       return instances;
    }
    

    调用getSpringFactoriesInstances(SpringApplicationRunListener.class, types, this, args)通过反射实例化EventPublishingRunListener

    EventPublishingRunListener实例化

    public EventPublishingRunListener(SpringApplication application, String[] args) {
       this.application = application;
       // 命令行参数
       this.args = args;
       // 事件多播器
       this.initialMulticaster = new SimpleApplicationEventMulticaster();
       /**
        * org.springframework.boot.devtools.restart.RestartApplicationListener,
        * org.springframework.boot.cloud.CloudFoundryVcapEnvironmentPostProcessor,
        * org.springframework.boot.context.config.ConfigFileApplicationListener,
        * org.springframework.boot.context.config.AnsiOutputApplicationListener,
        * org.springframework.boot.context.logging.LoggingApplicationListener,
        * org.springframework.boot.context.logging.ClasspathLoggingApplicationListener,
        * org.springframework.boot.autoconfigure.BackgroundPreinitializer,
        * org.springframework.boot.context.config.DelegatingApplicationListener,
        * org.springframework.boot.builder.ParentContextCloserApplicationListener,
        * org.springframework.boot.devtools.logger.DevToolsLogFactory$Listener,
        * org.springframework.boot.ClearCachesApplicationListener,
        * org.springframework.boot.context.FileEncodingApplicationListener,
        * org.springframework.boot.liquibase.LiquibaseServiceLocatorApplicationListener
        */
       for (ApplicationListener<?> listener : application.getListeners()) {
          this.initialMulticaster.addApplicationListener(listener);
       }
    }
    

    依赖关系图谱

    SimpleApplicationEventMulticaster

    SimpleApplicationEventMulticaster实例化

    此源码为AbstractApplicationEventMulticaster中方法。

    @Override
    public void addApplicationListener(ApplicationListener<?> listener) {
       synchronized (this.defaultRetriever) {
          // Explicitly remove target for a proxy, if registered already,
          // in order to avoid double invocations of the same listener.
          // 删除代理的目标(如果已注册),以避免重复调用同一侦听器,暂时没有发现有哪个监听器符合条件
          Object singletonTarget = AopProxyUtils.getSingletonTarget(listener);
          if (singletonTarget instanceof ApplicationListener) {
             this.defaultRetriever.applicationListeners.remove(singletonTarget);
          }
           
          // 添加目标 
          this.defaultRetriever.applicationListeners.add(listener);
          // 清理检索缓存 
          this.retrieverCache.clear();
       }
    }
    

    启动监听器

    listeners.starting();

    void starting() {
       // org.springframework.boot.context.event.EventPublishingRunListener
       for (SpringApplicationRunListener listener : this.listeners) {
          listener.starting();
       }
    }
    

    调用EventPublishingRunListener中的starting()方法。

    @Override
    public void starting() {
       // 构造EventObject事件, source为application并广播事件,通知各个监听器
       this.initialMulticaster.multicastEvent(new ApplicationStartingEvent(this.application, this.args));
    }
    

    广播Event

    @Override
    public void multicastEvent(ApplicationEvent event) {
       // 过滤监听器,为其广播事件。resolveDefaultEventType(event)除了`org.springframework.http.client.PublisherEntity`和`org.springframework.context.PayloadApplicationEvent`其余返回new ResolvableType(clazz)
       multicastEvent(event, resolveDefaultEventType(event));
    }
    
    @Override
    public void multicastEvent(final ApplicationEvent event, @Nullable ResolvableType eventType) {
       ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType(event));
       Executor executor = getTaskExecutor();
       /**
        * 返回与给定事件类型匹配的ApplicationListeners的集合。不匹配的监听器会被排除在外。
        * org.springframework.boot.devtools.restart.RestartApplicationListener,
        * org.springframework.boot.context.logging.LoggingApplicationListener,
        * org.springframework.boot.autoconfigure.BackgroundPreinitializer,
        * org.springframework.boot.context.config.DelegatingApplicationListener,
        * org.springframework.boot.liquibase.LiquibaseServiceLocatorApplicationListener
        */
       for (ApplicationListener<?> listener : getApplicationListeners(event, type)) {
          if (executor != null) {
             executor.execute(() -> invokeListener(listener, event));
          }
          else {
             // 用给定的事件调用给定的监听器。
             invokeListener(listener, event);
          }
       }
    }
    
    protected void invokeListener(ApplicationListener<?> listener, ApplicationEvent event) {
       ErrorHandler errorHandler = getErrorHandler();
       if (errorHandler != null) {
          try {
             doInvokeListener(listener, event);
          }
          catch (Throwable err) {
             errorHandler.handleError(err);
          }
       }
       else {
          doInvokeListener(listener, event);
       }
    }
    
    @SuppressWarnings({"rawtypes", "unchecked"})
    private void doInvokeListener(ApplicationListener listener, ApplicationEvent event) {
       try {
          listener.onApplicationEvent(event);
       }
       catch (ClassCastException ex) {
          String msg = ex.getMessage();
          if (msg == null || matchesClassCastMessage(msg, event.getClass())) {
             // Possibly a lambda-defined listener which we could not resolve the generic event type for
             // -> let's suppress the exception and just log a debug message.
             Log logger = LogFactory.getLog(getClass());
             if (logger.isTraceEnabled()) {
                logger.trace("Non-matching event type for listener: " + listener, ex);
             }
          }
          else {
             throw ex;
          }
       }
    }
    
  • 相关阅读:
    gThumb 3.1.2 发布,支持 WebP 图像
    航空例行天气预报解析 metaf2xml
    Baruwa 1.1.2 发布,邮件监控系统
    Bisect 1.3 发布,Caml 代码覆盖测试
    MoonScript 0.2.2 发布,基于 Lua 的脚本语言
    Varnish 入门
    快速增量备份程序 DeltaCopy
    恢复模糊的图像 SmartDeblur
    Cairo 1.12.8 发布,向量图形会图库
    iText 5.3.4 发布,Java 的 PDF 开发包
  • 原文地址:https://www.cnblogs.com/chinda/p/14308610.html
Copyright © 2020-2023  润新知