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);
			}
		}
相关文章
相关标签/搜索