SpringBoot源码阅读(10)——后处理器

后处理器是在监听器EnvironmentPostProcessorApplicationListener中被加载。
入口在SpringApplication实例方法prepareEnvironment,第343行。

listeners.environmentPrepared(bootstrapContext, environment);

这里触发了事件ApplicationEnvironmentPreparedEvent
相关监听器

监听器Order
DelegatingApplicationListener0
EnvironmentPostProcessorApplicationListenerInteger.MIN_VALUE + 10
LoggingApplicationListenerInteger.MIN_VALUE + 20
AnsiOutputApplicationListenerInteger.MIN_VALUE + 11
FileEncodingApplicationListenerInteger.MAX_VALUE

排序后,触发顺序

  1. DelegatingApplicationListener
  2. EnvironmentPostProcessorApplicationListener
  3. AnsiOutputApplicationListener
  4. LoggingApplicationListener
  5. FileEncodingApplicationListener

EnvironmentPostProcessorApplicationListener 就是监听器之一。

EnvironmentPostProcessorApplicationListener

主要方法

private void onApplicationEnvironmentPreparedEvent(ApplicationEnvironmentPreparedEvent event) {
	ConfigurableEnvironment environment = event.getEnvironment();
	SpringApplication application = event.getSpringApplication();
	for (EnvironmentPostProcessor postProcessor : getEnvironmentPostProcessors(application.getResourceLoader(),
			event.getBootstrapContext())) {
		postProcessor.postProcessEnvironment(environment, application);
	}
}
List<EnvironmentPostProcessor> getEnvironmentPostProcessors(ResourceLoader resourceLoader,
		ConfigurableBootstrapContext bootstrapContext) {
	ClassLoader classLoader = (resourceLoader != null) ? resourceLoader.getClassLoader() : null;
	EnvironmentPostProcessorsFactory postProcessorsFactory = this.postProcessorsFactory.apply(classLoader);
	return postProcessorsFactory.getEnvironmentPostProcessors(this.deferredLogs, bootstrapContext);
}

其中this.postProcessorsFactoryEnvironmentPostProcessorsFactory::fromSpringFactories

static EnvironmentPostProcessorsFactory fromSpringFactories(ClassLoader classLoader) {
	return new ReflectionEnvironmentPostProcessorsFactory(classLoader,
			SpringFactoriesLoader.loadFactoryNames(EnvironmentPostProcessor.class, classLoader));
}

EnvironmentPostProcessor的实现类

# Environment Post Processors
org.springframework.boot.env.EnvironmentPostProcessor=\
org.springframework.boot.cloud.CloudFoundryVcapEnvironmentPostProcessor,\
org.springframework.boot.context.config.ConfigDataEnvironmentPostProcessor,\
org.springframework.boot.env.RandomValuePropertySourceEnvironmentPostProcessor,\
org.springframework.boot.env.SpringApplicationJsonEnvironmentPostProcessor,\
org.springframework.boot.env.SystemEnvironmentPropertySourceEnvironmentPostProcessor,\
org.springframework.boot.reactor.DebugAgentEnvironmentPostProcessor

# Environment Post Processors
org.springframework.boot.env.EnvironmentPostProcessor=\
org.springframework.boot.autoconfigure.integration.IntegrationPropertiesEnvironmentPostProcessor
处理器Order值
CloudFoundryVcapEnvironmentPostProcessorInteger.MIN_VALUE + 10 - 1
ConfigDataEnvironmentPostProcessorInteger.MIN_VALUE + 10
RandomValuePropertySourceEnvironmentPostProcessorInteger.MIN_VALUE + 1
SpringApplicationJsonEnvironmentPostProcessorInteger.MIN_VALUE + 5
SystemEnvironmentPropertySourceEnvironmentPostProcessorInteger.MIN_VALUE + 5 - 1
DebugAgentEnvironmentPostProcessorInteger.MAX_VALUE
IntegrationPropertiesEnvironmentPostProcessorInteger.MAX_VALUE

最后顺序

  1. RandomValuePropertySourceEnvironmentPostProcessor
  2. SystemEnvironmentPropertySourceEnvironmentPostProcessor
  3. SpringApplicationJsonEnvironmentPostProcessor
  4. CloudFoundryVcapEnvironmentPostProcessor
  5. ConfigDataEnvironmentPostProcessor
  6. DebugAgentEnvironmentPostProcessor
  7. IntegrationPropertiesEnvironmentPostProcessor

EnvironmentPostProcessorApplicationListener实例化的时候,是调用的无参构造方法。

public EnvironmentPostProcessorApplicationListener() {
	this(EnvironmentPostProcessorsFactory::fromSpringFactories, new DeferredLogs());
}

实例化后关键属性

属性
postProcessorsFactoryEnvironmentPostProcessorsFactory::fromSpringFactories
deferredLogsDeferredLogFactory

ReflectionEnvironmentPostProcessorsFactory

实例化后的属性

属性
classesnull
classLoadernull
classNamesEnvironmentPostProcessor实现类的类全限定名\

加载EnvironmentPostProcessor实现类的主要逻辑

@Override
public List<EnvironmentPostProcessor> getEnvironmentPostProcessors(DeferredLogFactory logFactory,
		ConfigurableBootstrapContext bootstrapContext) {
	Instantiator<EnvironmentPostProcessor> instantiator = new Instantiator<>(EnvironmentPostProcessor.class,
			(parameters) -> {
				parameters.add(DeferredLogFactory.class, logFactory);
				parameters.add(Log.class, logFactory::getLog);
				parameters.add(ConfigurableBootstrapContext.class, bootstrapContext);
				parameters.add(BootstrapContext.class, bootstrapContext);
				parameters.add(BootstrapRegistry.class, bootstrapContext);
			});
	return (this.classes != null) ? instantiator.instantiateTypes(this.classes)
			: instantiator.instantiate(this.classLoader, this.classNames);
}
public Instantiator(Class<?> type, Consumer<AvailableParameters> availableParameters) {
	this(type, availableParameters, throwingFailureHandler);
}
public Instantiator(Class<?> type, Consumer<AvailableParameters> availableParameters,
			FailureHandler failureHandler) {
	this.type = type;
	this.availableParameters = getAvailableParameters(availableParameters);
	this.failureHandler = failureHandler;
}

Instantiator是一个通过用的实例化工具类。
主要逻辑:

  1. 获取要实例化的类的构造方法,按照构造方法的参数个数倒序排序。
  2. 然后检查每个参数,是否是给定参数集合中类的子类或者类本身。
  3. 如果找到了,就把给定参数集合中的值作为参数返回,拿去调用构造方法
  4. 优先使用个数多个的构造方法,默认使用无参构造
  5. 构造完成后,使用AnnotationAwareOrderComparator比较器排序一番。
属性
typeEnvironmentPostProcessor.class
availableParametersDeferredLogFactory.class factoryType -> DeferredLogs
Log.classlogFactory::getLog
ConfigurableBootstrapContext.classfactoryType -> bootstrapContext
BootstrapContext.classfactoryType -> bootstrapContext
BootstrapRegistry.classfactoryType -> bootstrapContext
failureHandler初始化失败后的处理器,默认是抛异常
RandomValuePropertySourceEnvironmentPostProcessor

构造方法

public RandomValuePropertySourceEnvironmentPostProcessor(Log logger) {
	this.logger = logger;
}
SystemEnvironmentPropertySourceEnvironmentPostProcessor

默认无参构造

SpringApplicationJsonEnvironmentPostProcessor

默认无参构造

CloudFoundryVcapEnvironmentPostProcessor

构造方法

public CloudFoundryVcapEnvironmentPostProcessor(Log logger) {
	this.logger = logger;
}
ConfigDataEnvironmentPostProcessor

构造方法

public ConfigDataEnvironmentPostProcessor(DeferredLogFactory logFactory,
			ConfigurableBootstrapContext bootstrapContext) {
	this(logFactory, bootstrapContext, null);
}

public ConfigDataEnvironmentPostProcessor(DeferredLogFactory logFactory,
		ConfigurableBootstrapContext bootstrapContext,
		ConfigDataEnvironmentUpdateListener environmentUpdateListener) {
	this.logFactory = logFactory;
	this.logger = logFactory.getLog(getClass());
	this.bootstrapContext = bootstrapContext;
	this.environmentUpdateListener = environmentUpdateListener;
}
DebugAgentEnvironmentPostProcessor

默认无参构造

IntegrationPropertiesEnvironmentPostProcessor

默认无参构造

最后得到各自的构造方法

构造方法
RandomValuePropertySourceEnvironmentPostProcessorpublic RandomValuePropertySourceEnvironmentPostProcessor(Log logger)
SystemEnvironmentPropertySourceEnvironmentPostProcessor无参构造
SpringApplicationJsonEnvironmentPostProcessor无参构造
CloudFoundryVcapEnvironmentPostProcessorpublic CloudFoundryVcapEnvironmentPostProcessor(Log logger)
ConfigDataEnvironmentPostProcessorpublic ConfigDataEnvironmentPostProcessor(DeferredLogFactory logFactoryConfigurableBootstrapContext bootstrapContext)
DebugAgentEnvironmentPostProcessor无参构造
IntegrationPropertiesEnvironmentPostProcessor无参构造
实例化后排序
  1. RandomValuePropertySourceEnvironmentPostProcessor
  2. SystemEnvironmentPropertySourceEnvironmentPostProcessor
  3. SpringApplicationJsonEnvironmentPostProcessor
  4. CloudFoundryVcapEnvironmentPostProcessor
  5. ConfigDataEnvironmentPostProcessor
  6. DebugAgentEnvironmentPostProcessor
  7. IntegrationPropertiesEnvironmentPostProcessor

逻辑

RandomValuePropertySourceEnvironmentPostProcessor

@Override
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
	RandomValuePropertySource.addToEnvironment(environment, this.logger);
}

这个处理器会创建一个Random对象,放入sourceskeyrandom
如果环境变量已经加载,就放在环境变量后面,没有加载,就放到最后

SystemEnvironmentPropertySourceEnvironmentPostProcessor

@Override
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
	String sourceName = StandardEnvironment.SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME;
	PropertySource<?> propertySource = environment.getPropertySources().get(sourceName);
	if (propertySource != null) {
		replacePropertySource(environment, sourceName, propertySource, application.getEnvironmentPrefix());
	}
}

@SuppressWarnings("unchecked")
private void replacePropertySource(ConfigurableEnvironment environment, String sourceName,
		PropertySource<?> propertySource, String environmentPrefix) {
	Map<String, Object> originalSource = (Map<String, Object>) propertySource.getSource();
	SystemEnvironmentPropertySource source = new OriginAwareSystemEnvironmentPropertySource(sourceName,
			originalSource, environmentPrefix);
	environment.getPropertySources().replace(sourceName, source);
}

这个处理器会处理系统环境变量,把系统环境变量包装成OriginAwareSystemEnvironmentPropertySource

SpringApplicationJsonEnvironmentPostProcessor

@Override
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
	MutablePropertySources propertySources = environment.getPropertySources();
	propertySources.stream().map(JsonPropertyValue::get).filter(Objects::nonNull).findFirst()
			.ifPresent((v) -> processJson(environment, v));
}
private void processJson(ConfigurableEnvironment environment, JsonPropertyValue propertyValue) {
	JsonParser parser = JsonParserFactory.getJsonParser();
	Map<String, Object> map = parser.parseMap(propertyValue.getJson());
	if (!map.isEmpty()) {
		addJsonPropertySource(environment, new JsonPropertySource(propertyValue, flatten(map)));
	}
}
public static JsonParser getJsonParser() {
	if (ClassUtils.isPresent("com.fasterxml.jackson.databind.ObjectMapper", null)) {
		return new JacksonJsonParser();
	}
	if (ClassUtils.isPresent("com.google.gson.Gson", null)) {
		return new GsonJsonParser();
	}
	if (ClassUtils.isPresent("org.yaml.snakeyaml.Yaml", null)) {
		return new YamlJsonParser();
	}
	return new BasicJsonParser();
}

这个处理器会从环境变量中获取spring.application.json或者SPRING_APPLICATION_JSON的配置,然后找到第一个配置,使用json解析器解析,放入source,名称为spring.application.json,位置在servletContextInitParams或者servletConfigInitParams之前。

CloudFoundryVcapEnvironmentPostProcessor

@Override
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
	if (CloudPlatform.CLOUD_FOUNDRY.isActive(environment)) {
		Properties properties = new Properties();
		JsonParser jsonParser = JsonParserFactory.getJsonParser();
		addWithPrefix(properties, getPropertiesFromApplication(environment, jsonParser), "vcap.application.");
		addWithPrefix(properties, getPropertiesFromServices(environment, jsonParser), "vcap.services.");
		MutablePropertySources propertySources = environment.getPropertySources();
		if (propertySources.contains(CommandLinePropertySource.COMMAND_LINE_PROPERTY_SOURCE_NAME)) {
			propertySources.addAfter(CommandLinePropertySource.COMMAND_LINE_PROPERTY_SOURCE_NAME,
					new PropertiesPropertySource("vcap", properties));
		}
		else {
			propertySources.addFirst(new PropertiesPropertySource("vcap", properties));
		}
	}
}

这个处理器,会从环境变量获取spring.main.cloud-platform的值,如果是CloudPlatform.CLOUD_FOUNDRY类型,如果值是CLOUD_FOUNDRY或者包含VCAP_APPLICATIONVCAP_SERVICES,就执行开源云平台的逻辑。
从环境变量中获取VCAP_APPLICATION VCAP_SERVICES的值,用json解析器解析,分别加上前缀vcap.application.vcap.services.,放入sources,名称是vcap,位置上,如果有命令行参数,就放在命令行参数后面,如果没有,就放首位。

ConfigDataEnvironmentPostProcessor

@Override
public void postProcessEnvironment(ConfigurableEnvironment environment, SpringApplication application) {
	postProcessEnvironment(environment, application.getResourceLoader(), application.getAdditionalProfiles());
}
ConfigDataEnvironment getConfigDataEnvironment(ConfigurableEnvironment environment, ResourceLoader resourceLoader,
			Collection<String> additionalProfiles) {
	return new ConfigDataEnvironment(this.logFactory, this.bootstrapContext, environment, resourceLoader,
			additionalProfiles, this.environmentUpdateListener);
}

创建一个ConfigDataEnvironment实例,过程中会创建一个ConfigDataLocationResolvers实例。

ConfigDataEnvironment(DeferredLogFactory logFactory, ConfigurableBootstrapContext bootstrapContext,
			ConfigurableEnvironment environment, ResourceLoader resourceLoader, Collection<String> additionalProfiles,
			ConfigDataEnvironmentUpdateListener environmentUpdateListener) {
	Binder binder = Binder.get(environment);
	UseLegacyConfigProcessingException.throwIfRequested(binder);
	this.logFactory = logFactory;
	this.logger = logFactory.getLog(getClass());
	this.notFoundAction = binder.bind(ON_NOT_FOUND_PROPERTY, ConfigDataNotFoundAction.class)
			.orElse(ConfigDataNotFoundAction.FAIL);
	this.bootstrapContext = bootstrapContext;
	this.environment = environment;
	this.resolvers = createConfigDataLocationResolvers(logFactory, bootstrapContext, binder, resourceLoader);
	this.additionalProfiles = additionalProfiles;
	this.environmentUpdateListener = (environmentUpdateListener != null) ? environmentUpdateListener
			: ConfigDataEnvironmentUpdateListener.NONE;
	this.loaders = new ConfigDataLoaders(logFactory, bootstrapContext, resourceLoader.getClassLoader());
	this.contributors = createContributors(binder);
}

感觉像是捅了马蜂窝了。
ConfigDataLocationResolvers实例化,会加载ConfigDataLocationResolver的实现类。

# ConfigData Location Resolvers
org.springframework.boot.context.config.ConfigDataLocationResolver=\
org.springframework.boot.context.config.ConfigTreeConfigDataLocationResolver,\
org.springframework.boot.context.config.StandardConfigDataLocationResolver

ConfigTreeConfigDataLocationResolver实例化,会创建LocationResourceLoader实例
StandardConfigDataLocationResolver实例化,会加载PropertySourceLoader的实现类

# PropertySource Loaders
org.springframework.boot.env.PropertySourceLoader=\
org.springframework.boot.env.PropertiesPropertySourceLoader,\
org.springframework.boot.env.YamlPropertySourceLoader

StandardConfigDataLocationResolver中会设置应用的配置文件名称,key是spring.config.name,默认值是application,也就是Spring配置文件的名字也是可以配置的,这个名字中不能包含*号。
至于PropertiesPropertySourceLoaderYamlPropertySourceLoader,就是解析Spring配置文件的两个加载器,前者解析properties后缀文件,后者解析yml后缀文件。
ConfigDataLocationResolvers中,在加载完成ConfigDataLocationResolver的接口后,会重新排序,把StandardConfigDataLocationResolver的子类或本身保留最后实现,放入集合末尾。

ConfigDataEnvironment实例化时,会创建ConfigDataLoaders实例,进而加载ConfigDataLoader的实例。

# ConfigData Loaders
org.springframework.boot.context.config.ConfigDataLoader=\
org.springframework.boot.context.config.ConfigTreeConfigDataLoader,\
org.springframework.boot.context.config.StandardConfigDataLoader

然后调用processAndApply,会读取配置文件。

void processAndApply() {
	ConfigDataImporter importer = new ConfigDataImporter(this.logFactory, this.notFoundAction, this.resolvers,
			this.loaders);
	registerBootstrapBinder(this.contributors, null, DENY_INACTIVE_BINDING);
	ConfigDataEnvironmentContributors contributors = processInitial(this.contributors, importer);
	ConfigDataActivationContext activationContext = createActivationContext(
			contributors.getBinder(null, BinderOption.FAIL_ON_BIND_TO_INACTIVE_SOURCE));
	contributors = processWithoutProfiles(contributors, importer, activationContext);
	activationContext = withProfiles(contributors, activationContext);
	contributors = processWithProfiles(contributors, importer, activationContext);
	applyToEnvironment(contributors, activationContext, importer.getLoadedLocations(),
			importer.getOptionalLocations());
}

private ConfigDataEnvironmentContributors processInitial(ConfigDataEnvironmentContributors contributors,
		ConfigDataImporter importer) {
	this.logger.trace("Processing initial config data environment contributors without activation context");
	contributors = contributors.withProcessedImports(importer, null);
	registerBootstrapBinder(contributors, null, DENY_INACTIVE_BINDING);
	return contributors;
}
  • 11
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值