(1). 概述

前面,通过一个小小的案例,有了一个入门,在这里,开始深入研究下:Spring Cloud Bus的源码,入口点在于:spring.factories

(2). BusEnvironmentPostProcessor

BusEnvironmentPostProcessor实现了EnvironmentPostProcessor,所以,Spring启动时,会首先回调:EnvironmentPostProcessor的所有实现.通过EnvironmentPostProcessor我们可以扩展自定义的配置信息.

package org.springframework.cloud.bus;

import java.util.HashMap;
import java.util.Map;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.env.EnvironmentPostProcessor;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.MapPropertySource;
import org.springframework.core.env.MutablePropertySources;
import org.springframework.core.env.PropertySource;


public class BusEnvironmentPostProcessor implements EnvironmentPostProcessor {

	private static final String PROPERTY_SOURCE_NAME = "defaultProperties";

	@Override
	public void postProcessEnvironment(ConfigurableEnvironment environment,
			SpringApplication application) {
		Map<String, Object> map = new HashMap<String, Object>();
		
		// 1. 构建参数
		// key    = spring.cloud.stream.bindings.springCloudBusOutput.content-type
		// value  = application/json 
		map.put("spring.cloud.stream.bindings." + SpringCloudBusClient.OUTPUT + ".content-type" , environment.getProperty("spring.cloud.bus.content-type", "application/json"));
		
		// key   = spring.cloud.bus.id
		// value = ${vcap.application.name:${spring.application.name:application}}:${vcap.application.instance_index:${spring.application.index:${local.server.port:${server.port:0}}}}:${vcap.application.instance_id:${random.value}} 
		// value的实际值为:${spring.application.name}:${server.port}:${random}
		map.put("spring.cloud.bus.id", getDefaultServiceId(environment));
		
		// 2. 往:Env(MutablePropertySources)里添加:PropertySource
		addOrReplace(environment.getPropertySources(), map);
	} // end postProcessEnvironment

	private void addOrReplace(MutablePropertySources propertySources, Map<String, Object> map) {
		MapPropertySource target = null;
		
		// 3. 判断:defaultProperties在env中是否存在
		if (propertySources.contains(PROPERTY_SOURCE_NAME)) {
			// 3.1 拿出对应的:PropertySource
			PropertySource<?> source = propertySources.get(PROPERTY_SOURCE_NAME);
			if (source instanceof MapPropertySource) {
				target = (MapPropertySource) source;
				// 3.2 遍历map,验证key是否存在,如果不存在,则添加.
				for (String key : map.keySet()) {
					if (!target.containsProperty(key)) {
						target.getSource().put(key, map.get(key));
					}
				}
			}
		}
		
		// 4. 构建一个:PropertySource
		if (target == null) {
			target = new MapPropertySource(PROPERTY_SOURCE_NAME, map);
		}
		
		// 5. 添加到MutablePropertySources的末尾.
		if (!propertySources.contains(PROPERTY_SOURCE_NAME)) {
			propertySources.addLast(target);
		}
	}// end addOrReplace
	
	
	// TODO: move this to commons
	private String getDefaultServiceId(ConfigurableEnvironment environment) {
		return "${vcap.application.name:${spring.application.name:application}}:${vcap.application.instance_index:${spring.application.index:${local.server.port:${server.port:0}}}}:${vcap.application.instance_id:${random.value}}";
	} // end getDefaultServiceId
}

(3). 总结

BusEnvironmentPostProcessor好像比较简单,就是在Env(MutablePropertySources),里添加一个:PropertySource(PropertySource的配置信息的载体).