1. 程式人生 > >springboot啟動過程(1)-初始化

springboot啟動過程(1)-初始化

好的 事件監聽 spa 兩個 包括 servlet 實例對象 ice 機制

1 springboot啟動時,[email protected]函數,執行SpringApplication.run(DemoApplication.class, args)即可,這裏初始化了一個SpringApplication實例,然後調用run啟動springboot。run方法中,調用了initialize,如下

@SuppressWarnings({ "unchecked", "rawtypes" })
private void initialize(Object[] sources) {

//把傳入的source設置到SpringApplication的變量中
  if (sources != null && sources.length > 0) {
    this.sources.addAll(Arrays.asList(sources));
  }

// 如果是web程序,設置web環境。web程序必須讓類加載器存在servlet 和 ConfigurableWebApplicationContext
  this.webEnvironment = deduceWebEnvironment();

//找到ApplicationContextInitializer類實例化為成員變量,這個過程是找到所有的初始化器。
  setInitializers((Collection) getSpringFactoriesInstances(ApplicationContextInitializer.class));
  //把ApplicationListener實例化為變量,就是找到所有的事件監聽器。

setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));

//找到入口類,即放置main函數的類。

  this.mainApplicationClass = deduceMainApplicationClass();
}

(1)初始化context。 上面setInitializers 得到了ApplicationContextInitializer類型對象的集合,ApplicationContextInitializer是一個可以用來初始化各種ApplicationContex的接口,就一個initialize方法,上面初始化的時候用到了getSpringFactoriesInstances方法如下,

private <T> Collection<? extends T> getSpringFactoriesInstances(Class<T> type,Class<?>[] parameterTypes, Object... args) {
  ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
  // Use names and ensure unique to protect against duplicates
  Set<String> names = new LinkedHashSet<String>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
  List<T> instances = createSpringFactoriesInstances(type, parameterTypes,classLoader, args, names);
  AnnotationAwareOrderComparator.sort(instances);
  return instances;
}

可以看到,方法用oadFactoryNames(type, classLoader));通過類型得到所有spring factories的名字,然後根據名字使用createSpringFactoriesInstances創造出實例對象,最後把創建好的對象排序並返回。springfactory是spring-boot-xxx(版本)包裏面的META-INF/spring.factories如下 ,然後通過createSpringFactoriesInstances方法利用反射創造出這些實例,實例共四個都是ApplicationContextInitializer的實現類,作用也如下。

# Application Context Initializers
org.springframework.context.ApplicationContextInitializer=\

//為ApplicationContext添加一個能夠檢查配置,在錯誤配置時能夠打印報錯信息的BeanFactoryPostProcessor
org.springframework.boot.context.ConfigurationWarningsApplicationContextInitializer,\

//為ApplicationContext設置id
org.springframework.boot.context.ContextIdApplicationContextInitializer,\

//從ApplicationContext的環境配置中,讀取Initializer並使用
org.springframework.boot.context.config.DelegatingApplicationContextInitializer,\

//為ApplicationContext設置一個環境變量,方便使用服務器正在監聽的端口號。
org.springframework.boot.context.embedded.ServerPortInfoApplicationContextInitializer

(2)初始化監聽器 上文中setListeners進行監聽器初始化操作,跟初始化context一樣,根據類型ApplicationListener.class從spring.factories裏找到各種監聽器,applicationListener就一個方法onApplicationEvent,用於監聽各種事件。

# Application Listeners
org.springframework.context.ApplicationListener=\
org.springframework.boot.ClearCachesApplicationListener,\
org.springframework.boot.builder.ParentContextCloserApplicationListener,\
org.springframework.boot.context.FileEncodingApplicationListener,\
org.springframework.boot.context.config.AnsiOutputApplicationListener,\
org.springframework.boot.context.config.ConfigFileApplicationListener,\
org.springframework.boot.context.config.DelegatingApplicationListener,\
org.springframework.boot.liquibase.LiquibaseServiceLocatorApplicationListener,\
org.springframework.boot.logging.ClasspathLoggingApplicationListener,\
org.springframework.boot.logging.LoggingApplicationListener

* applicationContext 事件機制 spring的事件機制基於觀察者模式,與所有的事件機制都基本類似,他們都需要 事件源, 事件 和事件監聽器 組成。只是此處的事件源是ApplicationContext。包括兩個重要部分,

ApplicationEvent: 容器事件,必須由 ApplicationContext發布。

   ApplicationListener: 監聽器,可有容器中的任何監聽器Bean擔任。

我們使用時可以定一個event繼承ApplicationEvent,然後定一個listener繼承ApplicationListener,實現onApplicationEvent方法,在方法裏可以根據事件類型判斷事件,進行響應處理。事件發布的時候,需要得到ApplicationContext,調用publishEvent(event)進行發布即可。spring也內置了幾個事件。

(3)上文的最後,deduceMainApplicationClass方法中,通過獲取當前方法調用棧,得到main函數的類,賦值給成員變量。

  

springboot啟動過程(1)-初始化