环境代表当前应用运行时所处的环境。
整个应用环境模型包括2个关键方面:
profiles配置组(以下简称组):
一个profile组,是一个以name名称命名的、逻辑上的、要被注册到容器中的BeanDefinition的集合。简单一点说,一个profile就代表一组BeanDefinition,这个对应配置文件中<beans profile="">。当加载解析xml配置文件的时候,只有active=true激活的BeanDefinition才会被加载进容器。properties环境变量:
在几乎所有的应用中,Properties环境变量都扮演着非常重要的角色,且这些变量值可以来自于各种PropertySource属性源,如:properties文件、jvm虚拟机环境变量、操作系统环境变量、JNDI、Servlet上下文参数、自定义的属性对象、Map对象,等等。Environment环境对象为用户提供了方便的接口,用于配置和使用属性源。
环境体系图如下:
刚才提到环境模型具有2个关键方面:profiles和properties,从体系图中可以看出,properties方面的所有功能由PropertyResolver属性解决器来实现,环境模型只是通过装饰模式,在PropertyResolver功能的基础上,额外扩展出了profiles方面的功能。因此在接口方面,Environment继承自PropertyResolver,从实现类方面,AbstractEnvironment类内部持有一个PropertySourcesPropertyResolver类型对象的引用。
关于PropertyResolver,我前边的文章已经进行了详细的解释,因此在本文中,我们重点关注环境模型在profiles方面的实现原理,体系图如下:
Environment接口:
public interface Environment extends PropertyResolver { /** * 获取当前环境对象激活的所有profile组。 * * @return */ String[] getActiveProfiles(); /** * 获取默认的profile组。 * 如果当前环境对象中激活的组为空(getActiveProfiles()返回空数组)的话, * 则会启用默认profile组。 * * @return */ String[] getDefaultProfiles(); /** * 判断给定的一个或多个组中,是否存在满足当前环境对象配置的组(任意一个组满足即可)。 * 如: * 调用acceptsProfiles("p1","!p2"),如果当前环境对象激活了p1, * 或者没有激活p2(注意是或,满足一个条件即可),则返回true,否则返回false。 * * @param profiles * @return */ boolean acceptsProfiles(String... profiles); }
ConfigurableEnvironment:
public interface ConfigurableEnvironment extends Environment, ConfigurablePropertyResolver { /** * 重新设置激活的组集合。 * @param profiles */ void setActiveProfiles(String... profiles); /** * 向当前激活的组集合中添加一个组。 * @param profile */ void addActiveProfile(String profile); /** * 设置默认激活的组集合。激活的组集合为空时会使用默认的组集合。 * * @param profiles */ void setDefaultProfiles(String... profiles); /** * 获取当前环境对象中的属性源集合,也就是应用环境变量。 * 属性源集合其实就是一个容纳PropertySource的容器。 * 这个方法提供了直接配置属性源的入口。 * @return */ MutablePropertySources getPropertySources(); /** * 获取操作系统环境变量 * 这个方法提供了直接配置系统环境变量的入口。 * @return */ Map<String, Object> getSystemEnvironment(); /** * 获取虚拟机环境变量 * 这个方法提供了直接配置虚拟机环境变量的入口。 * @return */ Map<String, Object> getSystemProperties(); /** * 合并指定环境对象中的配置到当前环境对象中。 * @param parent */ void merge(ConfigurableEnvironment parent); }
AbstractEnvironment抽象基类:
该类实际上实现了以上接口的所有方法,且额外扩展了自定义属性源的入口:
protected void customizePropertySources(MutablePropertySources propertySources);
但是因为初始时属性源集合只是一个空集合,没有任何意义,因为该类定义为抽象基类,不能直接实例化使用。部分代码如下:/** * 部分代码 * @author lixin * */ public class AbstractEnvironment { /** * 可变属性源集合 */ private final MutablePropertySources propertySources = new MutablePropertySources(); /** * 在构造方法中直接调用自定义属性源集合 */ public AbstractEnvironment() { customizePropertySources(this.propertySources); } /** * 自定义属性源集合, * 默认空实现,子类可重写,用来配置属性源。 * * @param propertySources */ protected void customizePropertySources(MutablePropertySources propertySources) { } }
StandardEnvironment:
该类定义了Spring应用运行时使用的标准环境,其实就是重写了customizePropertySources方法,先后追加了jvm虚拟机环境变量属性源和操作系统环境变量属性源这两个属性源。当然对于特殊的spring运行环境,我们可以创建标准环境的子类,以实现属性源的扩充,比如:StandardServletEnvironment类,用于web应用环境。public class StandardEnvironment extends AbstractEnvironment { // 操作系统环境变量属性源的名称 public static final String SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME = "systemEnvironment"; // jvm虚拟机系统环境变量属性源的名称 public static final String SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME = "systemProperties"; @Override 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())); } }
以上就是spring框架的基本环境体系。
来源:oschina
链接:https://my.oschina.net/u/2624635/blog/671055