spring boot 源碼分析(三) 配置文件加載3

1、前言java

    前兩篇文章咱們主要經過源碼分析了spring boot 加載配置文件的一些流程,接下來咱們繼續分析他是怎麼組裝,怎麼運行起來的。期間他經過什麼樣的方式加載咱們的核心配置 application.yml .spring

2、源碼分析app

    咱們回到咱們啓動用的主類less

@SpringBootApplication
public class StudyApplication {

    public static void main(String[] args) {
        SpringApplication.run(StudyApplication.class, args);
    }

}

進入SpringApplication.run()方法源碼分析

public static ConfigurableApplicationContext run(Class<?> primarySource,
			String... args) {
		return run(new Class<?>[] { primarySource }, args);
	}

這個方法以前介紹過,咱們繼續看他的重載方法run()性能

public static ConfigurableApplicationContext run(Class<?>[] primarySources,
			String[] args) {
		return new SpringApplication(primarySources).run(args);
	}

前兩節咱們已經講了new SpringApplication(primarySources)裏的內容,下面咱們看看他的run(args)主要作了些什麼this

/**
	 * 運行 Spring application, 建立和刷新成一個新的應用上下文
	 * {@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<>();//錯誤報告list
		configureHeadlessProperty();
		SpringApplicationRunListeners listeners = getRunListeners(args);//經過args獲取運行的監聽器
		listeners.starting();//開啓監聽器
		try {
			ApplicationArguments applicationArguments = new DefaultApplicationArguments(
					args);//args封裝到ApplicationArguments應用參數
			ConfigurableEnvironment environment = prepareEnvironment(listeners,
					applicationArguments);//將監聽器listeners和應用參數applicationArguments封裝到配置環境ConfigurableEnvironment中去
			configureIgnoreBeanInfo(environment);//配置一些要忽略的bean信息
			Banner printedBanner = printBanner(environment);
			context = createApplicationContext();//建立ApplicationContext
			exceptionReporters = getSpringFactoriesInstances(
					SpringBootExceptionReporter.class,
					new Class[] { ConfigurableApplicationContext.class }, context);//建立錯誤報告list
			prepareContext(context, environment, listeners, applicationArguments,
					printedBanner);//將environment配置環境,listeners監聽器列表,applicationArguments應用參數,printedBanner封裝到context中
			refreshContext(context);刷新應用上下文context
			afterRefresh(context, applicationArguments);//在應用上下文被刷新以後調用
			stopWatch.stop();//檢測性能結束點
			if (this.logStartupInfo) {//日誌記錄,這裏就用到了開始代碼提到的性能檢測點stopWatch
				new StartupInfoLogger(this.mainApplicationClass)
						.logStarted(getApplicationLog(), stopWatch);
			}
			listeners.started(context);//通知監聽器context已經啓動
			callRunners(context, applicationArguments);啓動
		}
		catch (Throwable ex) {
			handleRunFailure(context, ex, exceptionReporters, listeners);
			throw new IllegalStateException(ex);
		}

		try {
			listeners.running(context);//通知監聽器context正在運行
		}
		catch (Throwable ex) {
			handleRunFailure(context, ex, exceptionReporters, null);
			throw new IllegalStateException(ex);
		}
		return context;
	}

未完待續。。。debug

ConfigFileApplicationListener 主要業務加載類,具體的追蹤方法會在6月1日兒童節揭曉。
ConfigFileApplicationListener.Loader.load(PropertySourceLoader loader, String location, Profile profile,DocumentFilter filter, DocumentConsumer consumer)


private void load(PropertySourceLoader loader, String location, Profile profile,
				DocumentFilter filter, DocumentConsumer consumer) {
			try {
				Resource resource = this.resourceLoader.getResource(location);
				String description = getDescription(location, resource);
				if (profile != null) {
					description = description + " for profile " + profile;
				}
				if (resource == null || !resource.exists()) {
					this.logger.trace("Skipped missing config " + description);
					return;
				}
				if (!StringUtils.hasText(
						StringUtils.getFilenameExtension(resource.getFilename()))) {
					this.logger.trace("Skipped empty config extension " + description);
					return;
				}
				String name = "applicationConfig: [" + location + "]";
				List<Document> documents = loadDocuments(loader, name, resource);
				if (CollectionUtils.isEmpty(documents)) {
					this.logger.trace("Skipped unloaded config " + description);
					return;
				}
				List<Document> loaded = new ArrayList<>();
				for (Document document : documents) {
					if (filter.match(document)) {
						addActiveProfiles(document.getActiveProfiles());
						addProfiles(document.getIncludeProfiles());
						loaded.add(document);
					}
				}
				Collections.reverse(loaded);
				if (!loaded.isEmpty()) {
					loaded.forEach((document) -> consumer.accept(profile, document));
					this.logger.debug("Loaded config file " + description);
				}
			}
			catch (Exception ex) {
				throw new IllegalStateException("Failed to load property "
						+ "source from location '" + location + "'", ex);
			}
		}
相關文章
相關標籤/搜索