第五章 第一节 spring-connet之environment

前言

environment模块是大家都极少能用到,但是还是会被用的基础模块。把Environment当做一个map就好,可以从里面获得配置。这节让鸟菜啊写得苍白无力。太简单,用得少,还是要解读

源码解读

输入图片说明

Environment

public interface Environment extends PropertyResolver {
	// 得到活跃的配置信息
	String[] getActiveProfiles();
	// 得到默认的配置信息
	String[] getDefaultProfiles();
	// 判断活跃配置中是否有这些配置,一个配对,就返回true
	boolean acceptsProfiles(String... profiles);
}

实现代码

@Override
public String[] getActiveProfiles() {
	return StringUtils.toStringArray(doGetActiveProfiles());
}


protected Set<String> doGetActiveProfiles() {
	synchronized (this.activeProfiles) {
		// 如果没有活跃的配置
		if (this.activeProfiles.isEmpty()) {
			// 获得默认配置,默认情况下是没有默认配置的,需要通过getPropertySources设置才行
			String profiles = getProperty(ACTIVE_PROFILES_PROPERTY_NAME);
			if (StringUtils.hasText(profiles)) {
				setActiveProfiles(StringUtils.commaDelimitedListToStringArray(StringUtils.trimAllWhitespace(profiles)));
			}
		}
		return this.activeProfiles;
	}
}
public String[] getDefaultProfiles() {
		return StringUtils.toStringArray(doGetDefaultProfiles());
}

protected Set<String> doGetDefaultProfiles() {
	synchronized (this.defaultProfiles) {
		// 判断defaultProfiles 是否只有一个 befault的配置,
		if (this.defaultProfiles.equals(getReservedDefaultProfiles())) {
			// 获得默认配置,默认情况下是没有默认配置的,需要通过getPropertySources设置才行
			String profiles = getProperty(DEFAULT_PROFILES_PROPERTY_NAME);
			if (StringUtils.hasText(profiles)) {
				setDefaultProfiles(StringUtils.commaDelimitedListToStringArray(StringUtils.trimAllWhitespace(profiles)));
			}
		}
		return this.defaultProfiles;
	}
}
public boolean acceptsProfiles(String... profiles) {
	Assert.notEmpty(profiles, "Must specify at least one profile");
	for (String profile : profiles) {
		if (StringUtils.hasLength(profile) && profile.charAt(0) == '!') {
			if (!isProfileActive(profile.substring(1))) {
				return true;
			}
		} else if (isProfileActive(profile)) {
			return true;
		}
	}
	return false;
}
protected boolean isProfileActive(String profile) {
	validateProfile(profile);
	Set<String> currentActiveProfiles = doGetActiveProfiles();
	return (currentActiveProfiles.contains(profile) ||(currentActiveProfiles.isEmpty() && doGetDefaultProfiles().contains(profile)));
}

ConfigurableEnvironment

public interface ConfigurableEnvironment extends Environment, ConfigurablePropertyResolver {

	void setActiveProfiles(String... profiles);

	void addActiveProfile(String profile);

	void setDefaultProfiles(String... profiles);

	MutablePropertySources getPropertySources();

	Map<String, Object> getSystemEnvironment();

	Map<String, Object> getSystemProperties();

	void merge(ConfigurableEnvironment parent);
}
@Override
public void setActiveProfiles(String... profiles) {
	Assert.notNull(profiles, "Profile array must not be null");
	synchronized (this.activeProfiles) {
		// 先清空活跃配置
		this.activeProfiles.clear();
		for (String profile : profiles) {
			validateProfile(profile);
			this.activeProfiles.add(profile);
		}
	}
}

@Override
public void addActiveProfile(String profile) {
	if (this.logger.isDebugEnabled()) {
		this.logger.debug(String.format("Activating profile '%s'", profile));
	}
	validateProfile(profile);
	// 会添加默认配置
	// 活跃配置里面为null,获得默认的活跃配置比如 active,那么活跃配置里面存在一个active
	doGetActiveProfiles();
	synchronized (this.activeProfiles) {
		this.activeProfiles.add(profile);
	}
}
@Override
public void setDefaultProfiles(String... profiles) {
	Assert.notNull(profiles, "Profile array must not be null");
	synchronized (this.defaultProfiles) {
		// 先清空活跃配置
		this.defaultProfiles.clear();
		for (String profile : profiles) {
			validateProfile(profile);
			this.defaultProfiles.add(profile);
		}
	}
}
public Map<String, Object> getSystemEnvironment() {
	if (suppressGetenvAccess()) {
		return Collections.emptyMap();
	}
	try {
		// 获得系统环境,想知道系统环境里面有哪些数据,可以使用打印System.getenv()
		return (Map) System.getenv();
	}catch (AccessControlException ex) {
		......
	}
}


@Override
@SuppressWarnings({"unchecked", "rawtypes"})
public Map<String, Object> getSystemProperties() {
	try {
		// 获得系统配置,想知道系统环境里面有哪些数据,可以使用打印System.getProperties()
		return (Map) System.getProperties();
	}
	catch (AccessControlException ex) {
		.......
	}
}
private final MutablePropertySources propertySources = new MutablePropertySources(this.logger);

public MutablePropertySources getPropertySources() {
	return this.propertySources;
}
public class MutablePropertySources implements PropertySources {

	private final List<PropertySource<?>> propertySourceList = new CopyOnWriteArrayList<PropertySource<?>>();
}

MutablePropertySources相当于一个list。只是比list多一些操作。比如添加到哪个元素之前,或之后等等。类似于redis的list。里面保存了PropertySource

PropertySource
public abstract class PropertySource<T> {

	protected final Log logger = LogFactory.getLog(getClass());

	protected final String name;
	// 被适配对象
	protected final T source;
}

public class ServletConfigPropertySource extends EnumerablePropertySource<ServletConfig> {

	public ServletConfigPropertySource(String name, ServletConfig servletConfig) {
		super(name, servletConfig);
	}

	@Override
	public String[] getPropertyNames() {
		return StringUtils.toStringArray(this.source.getInitParameterNames());
	}
	// 适配方法
	@Override
	public String getProperty(String name) {
		return this.source.getInitParameter(name);
	}

}

PropertySource 使用适配器模式。从被适配的对象中,获得数据。

StandardEnvironment

protected void customizePropertySources(MutablePropertySources propertySources) {
	propertySources.addLast(new MapPropertySource(SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME, getSystemProperties()));
	propertySources.addLast(new SystemEnvironmentPropertySource(SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, getSystemEnvironment()));
}

StandardServletEnvironment

protected void customizePropertySources(MutablePropertySources propertySources) {
	propertySources.addLast(new StubPropertySource(SERVLET_CONFIG_PROPERTY_SOURCE_NAME));
	propertySources.addLast(new StubPropertySource(SERVLET_CONTEXT_PROPERTY_SOURCE_NAME));
	if (JndiLocatorDelegate.isDefaultJndiEnvironmentAvailable()) {
		// 准备JNDI配置
		propertySources.addLast(new JndiPropertySource(JNDI_PROPERTY_SOURCE_NAME));
	}
	super.customizePropertySources(propertySources);
}

@Override
public void initPropertySources(ServletContext  servletContext, ServletConfig servletConfig) {
	// 把ServletContext 与ServletConfig 加入PropertySources
	WebApplicationContextUtils.initServletPropertySources(getPropertySources(), servletContext, servletConfig);
}

在容器内获得

public class ConsumersTest implements EnvironmentAware{
	
	private Environment environment;
	
	@Override
	public void setEnvironment( Environment environment ) {
		this.environment = environment;
		
	}
}

只要实现EnvironmentAware接口,spring上下文容器,就主动的注入的

总结

有什么用

  1. 可以得到系统参数与环境参数
  2. 如果是web项目可以得到web配置信息
  3. environment具有扩张性,spring运行在其他软件环境里面只要扩展,使用者就可以得到环境配置

实现细节

  1. 调用setActiveProfiles和setDefaultProfiles的时候,会清空之前的配置数据、
	@Test
	public void test(){
		ConfigurableEnvironment environment = new StandardEnvironment();
		String[] active = environment.getActiveProfiles( );
		System.out.println("Environment init time : " + Arrays.asList(active) );
		environment.addActiveProfile( "niaocaia" );
		environment.addActiveProfile( "niaocai------" );
		active = environment.getActiveProfiles( );
		System.out.println( "ConfigurableEnvironment.addActiveProfile  getActiveProfiles" + Arrays.asList(active) );
		
		environment.setActiveProfiles( "setActiveProfiles" );
		active = environment.getActiveProfiles( );
		System.out.println( "ConfigurableEnvironment.setActiveProfiles  getActiveProfiles" + Arrays.asList(active) );
		
	}

Environment init time : []
ConfigurableEnvironment.addActiveProfile  getActiveProfiles[niaocaia, niaocai------]
ConfigurableEnvironment.setActiveProfiles  getActiveProfiles[setActiveProfiles]
  1. 得到系统与环境配置
	@Test
	public void systemprofile(){
		ConfigurableEnvironment environment = new StandardEnvironment();
		System.out.println( environment.getSystemEnvironment( ) +"\\r\\n");
		System.out.println( environment.getSystemProperties( ) );
	}
  1. 如果是web项目,可以从Environment得到ServletContext与 ServletConfig的配置
  2. PropertySource对象是对Environment可以扩展做了设计
ConfigurableEnvironment environment = new StandardEnvironment();
environment.getPropertySources( ).addFirst( new PropertySource< String > (null){
	@Override
	public Object getProperty( String name ) {
		// TODO 自动生成的方法存根
		return null;
	}
});

猜你喜欢

转载自my.oschina.net/u/1261452/blog/1801158
今日推荐