springboot啓動分析

springboot啓動分析

一、啓動類 

	@SpringBootApplication
	public class SpringBootStudyApplication {

		public static void main(String[] args) {
			// spring boot 啓動入口
			SpringApplication.run(SpringBootStudyApplication.class, args);
		}

	}

 二、實例化SpringApplication對象

	// org.springframework.boot.SpringApplication.SpringApplication
	// SpringApplication的靜態run方法,進入重載方法run
	public static ConfigurableApplicationContext run(Class<?> primarySource,
			String... args) {
		return run(new Class<?>[] { primarySource }, args);
	}
	
	// 實例化SpringApplication對象,然後調用成員方法run(args)
	public static ConfigurableApplicationContext run(Class<?>[] primarySources,
			String[] args) {
		return new SpringApplication(primarySources).run(args);
	}
	// 進入構造器重載方法
	public SpringApplication(Class<?>... primarySources) {
		this(null, primarySources);
	}
	// 實例化SpringApplication
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public SpringApplication(ResourceLoader resourceLoader, Class<?>... primarySources) {
		this.resourceLoader = resourceLoader;
		Assert.notNull(primarySources, "PrimarySources must not be null");
		// 將配置的class保存起來
		this.primarySources = new LinkedHashSet<>(Arrays.asList(primarySources));
		// 自動推斷出webApplication容器的類型(servlet)
		this.webApplicationType = WebApplicationType.deduceFromClasspath();
		// 從META-INF/spring.factories文件中讀取ApplicationContextInitializer實現類,並且實例化(ApplicationContextInitializer接口在spring-context包下,只有一個抽象方法,可以在spring容器refresh刷新前進行一些其他操作)
		setInitializers((Collection) getSpringFactoriesInstances(
				ApplicationContextInitializer.class));
		// 從META-INF/spring.factories文件中讀取ApplicationListener實現類
		setListeners((Collection) getSpringFactoriesInstances(ApplicationListener.class));
		// 從參數primarySources數組中推斷出存在main方法的class
		this.mainApplicationClass = deduceMainApplicationClass();
	}


三、調用SpringApplication的run(args)方法 

AbstractApplicationContext.refresh()分析

	/**
	 * Run the Spring application, creating and refreshing a new
	 * {@link ApplicationContext}.
	 * @param args the application arguments (usually passed from a Java main method)
	 * @return a running {@link ApplicationContext}
	 */
	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實現類,並且實例化
		//(SpringApplicationRunListener實現類必須要有一個帶參的構造器,參數列表是:SpringApplication application, String[] args),
		// listeners保存了SpringApplicationRunListener集合
		SpringApplicationRunListeners listeners = getRunListeners(args);
		// 該方法其實調用的是遍歷SpringApplicationRunListener的同名方法starting()
		listeners.starting();
		try {
			ApplicationArguments applicationArguments = new DefaultApplicationArguments(
					args);
			// 準備配置環境
			ConfigurableEnvironment environment = prepareEnvironment(listeners,
					applicationArguments);
			// 忽視一些bean類
			configureIgnoreBeanInfo(environment);
			// 打印banner圖標
			Banner printedBanner = printBanner(environment);
			// 根據前面構造器方法中推斷出的容器類型來創建ApplicationContext容器
			context = createApplicationContext();
			// 從spring.factories文件中獲取異常報告器,根據參數進行實例化
			exceptionReporters = getSpringFactoriesInstances(
					SpringBootExceptionReporter.class,
					new Class[] { ConfigurableApplicationContext.class }, context);
			// 準備context容器,會調用ApplicationContextInitializer實現類的initial方法
			prepareContext(context, environment, listeners, applicationArguments,
					printedBanner);
   			// 會調用AbstractApplicationContext的refresh()方法
			refreshContext(context);
			// 容器刷新後處理,默認空方法,讓子類進行實現
			afterRefresh(context, applicationArguments);
			// 統計運行的時間,進行打印日誌
			stopWatch.stop();
			if (this.logStartupInfo) {
				new StartupInfoLogger(this.mainApplicationClass)
						.logStarted(getApplicationLog(), stopWatch);
			}
			// 遍歷調用SpringApplicationRunListener的started(context)方法
			listeners.started(context);
			// 調用ApplicationRunner和CommandLineRunner的run方法
			callRunners(context, applicationArguments);
		}
		catch (Throwable ex) {
			handleRunFailure(context, ex, exceptionReporters, listeners);
			throw new IllegalStateException(ex);
		}

		try {
			// 遍歷調用SpringApplicationRunListener的started(context)方法
			listeners.running(context);
		}
		catch (Throwable ex) {
			handleRunFailure(context, ex, exceptionReporters, null);
			throw new IllegalStateException(ex);
		}
		return context;
	}

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章