Spring Boot

    Spring Boot的初始化時從一個main方法開始,進入調用到SpringApplication的內部去實現java

 

首先調用的是web

 

進入這個類的內部就是spring

繼續tomcat

核心就是從這個new方法開始,run(args)開始執行各類初始化環境的操做springboot

 

首先咱們來看這個構造方法app

 

這個方法調用的是initialize方法區初始化各類須要的條件環境less

private void initialize(Object[] sources) {
		if (sources != null && sources.length > 0) {
			this.sources.addAll(Arrays.asList(sources));
		}
//經過判斷是否能加載到Servlate跟ConfigurableWebApplicationContext這個類去判讀是否爲web環境
		this.webEnvironment = deduceWebEnvironment();
//讀取spring.factories文件中的org.springframework.context.ApplicationContextInitializer對應的各類類名,而後加載內存建立好,爲了下面使用
		setInitializers((Collection) getSpringFactoriesInstances(
				ApplicationContextInitializer.class));
//讀取spring.factories文件中的org.springframework.context.ApplicationListener對應的各類類名,而後加載內存建立好,爲了下面使用
	setListeners((Collection)getSpringFactoriesInstances(ApplicationListener.class));
//肯定main方法所在的類
		this.mainApplicationClass = deduceMainApplicationClass();
	}

以一個方法爲例子this

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
//這是根據spring.facotories文件獲得的value都是一些SpringApplicationRunListener的實現類的全類名稱
   Set<String> names = new LinkedHashSet<String>(
         SpringFactoriesLoader.loadFactoryNames(type, classLoader));
//加載到內存並初始化實例
   List<T> instances = createSpringFactoriesInstances(type, parameterTypes,
         classLoader, args, names);
//根據實例的名稱排序
   AnnotationAwareOrderComparator.sort(instances);
   return instances;
}

值得小注意的是:Spring使用的是線程上下文加載器,去加載的本身的各個模塊的jar中的類,由於爲了確保加載器必定是當前容器的加載器,才能夠加在到這些Class文件的,好比當前的環境是web環境,並且是tomcat的容器,因此這些jar文件是經過的tomcat的的類加載去加載的,而默認的線程上下文加載就是自定義的tomcat容器加載器,因此須要這樣去加載Class,其實就是經過類加載器能夠更換咱們想要的加載器spa

下面就是簡單的根據ClassLoader還有Class類型去加載類文件到內存,而後實例化的過程,而後返回這些實例對象線程

當須要的ApplicationContextInitializer、ApplicationListener實現類加載完成後,都會保存到SpringApplication這個類的對應的Map中

//保存ApplicationContextInitializer實現類的實例對象
public void setInitializers(
			Collection<? extends ApplicationContextInitializer<?>> initializers) {
		this.initializers = new ArrayList<ApplicationContextInitializer<?>>();
		this.initializers.addAll(initializers);

	}
//保存ApplicationListener實現類的的實例對象
public void setListeners(Collection<? extends ApplicationListener<?>> listeners) {
		this.listeners = new ArrayList<ApplicationListener<?>>();
		this.listeners.addAll(listeners);
	}

 

大概加載流程以下

至此springboot創造一個SpringApplication這個類,準備了實例化各類配置參數類,而後進入到真正的建立SpringContext整個環境的入口

public ConfigurableApplicationContext run(String... args) {
//建立一個監聽類StopWacht,記錄啓動的時間,加載類等信息輸出到log
		StopWatch stopWatch = new StopWatch();
		stopWatch.start();

		ConfigurableApplicationContext context = null;
		FailureAnalyzers analyzers = null;
//用來設置java.awt.headless 屬性是true 仍是false,是J2SE的一種模式用於在缺乏顯示屏、鍵盤    
    //或者鼠標時的系統配置
		configureHeadlessProperty();
//讀取spring.factory中配置初始化EventPublishingRunListener這個類
		SpringApplicationRunListeners listeners = getRunListeners(args);
//發送啓動事件到對應的各個監聽器中
		listeners.starting();
		try {
			ApplicationArguments applicationArguments = new DefaultApplicationArguments(
					args);
			ConfigurableEnvironment environment = prepareEnvironment(listeners,
					applicationArguments);
			Banner printedBanner = printBanner(environment);
			context = createApplicationContext();
			analyzers = new FailureAnalyzers(context);
			prepareContext(context, environment, listeners, applicationArguments,
					printedBanner);
			refreshContext(context);
			afterRefresh(context, applicationArguments);
			listeners.finished(context, null);
			stopWatch.stop();
			if (this.logStartupInfo) {
				new StartupInfoLogger(this.mainApplicationClass)
						.logStarted(getApplicationLog(), stopWatch);
			}
			return context;
		}
		catch (Throwable ex) {
			handleRunFailure(context, listeners, analyzers, ex);
			throw new IllegalStateException(ex);
		}
	}
相關文章
相關標籤/搜索