1. 程式人生 > 實用技巧 >SpringBoot原始碼學習(二) 釋出啟動事件

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();

      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例項化

此原始碼為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;
      }
   }
}