前言
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上下文容器,就主动的注入的
总结
有什么用
- 可以得到系统参数与环境参数
- 如果是web项目可以得到web配置信息
- environment具有扩张性,spring运行在其他软件环境里面只要扩展,使用者就可以得到环境配置
实现细节
- 调用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]
- 得到系统与环境配置
@Test
public void systemprofile(){
ConfigurableEnvironment environment = new StandardEnvironment();
System.out.println( environment.getSystemEnvironment( ) +"\\r\\n");
System.out.println( environment.getSystemProperties( ) );
}
- 如果是web项目,可以从Environment得到ServletContext与 ServletConfig的配置
- PropertySource对象是对Environment可以扩展做了设计
ConfigurableEnvironment environment = new StandardEnvironment();
environment.getPropertySources( ).addFirst( new PropertySource< String > (null){
@Override
public Object getProperty( String name ) {
// TODO 自动生成的方法存根
return null;
}
});