前言
Enviroment对象用来保证一些系统变量,环境边等等信息,那么再Spring中是在什么时候常见起来的呢,它的继承体系又是如何的呢?我们开发过程中能否对其进行DIY呢?本文将回答这些问题。
分析过程
首先通过Spring的启动过程看Environment最初是在哪里被使用到的,一路追进去,看this这个构造方法
AbstractApplicationContext的构造方法
public AbstractApplicationContext(@Nullable ApplicationContext parent) {
this();
setParent(parent);
}
public AbstractApplicationContext() {
// 资源模式处理器,用来解析系统运行需要的资源,比如配置文件,xml文件
this.resourcePatternResolver = getResourcePatternResolver();
}
protected ResourcePatternResolver getResourcePatternResolver() {
return new PathMatchingResourcePatternResolver(this);
}
setParent,这里是空
public void setParent(@Nullable ApplicationContext parent) {
this.parent = parent;
if (parent != null) {
Environment parentEnvironment = parent.getEnvironment();
if (parentEnvironment instanceof ConfigurableEnvironment) {
getEnvironment().merge((ConfigurableEnvironment) parentEnvironment);
}
}
}
这里有个getEnvironment方法,点进去看看
AbstractApplicationContext里面的getEnviroment方法,懒加载的方式去获取
public ConfigurableEnvironment getEnvironment() {
if (this.environment == null) {
this.environment = createEnvironment();
}
return this.environment;
}
protected ConfigurableEnvironment createEnvironment() {
return new StandardEnvironment();
}
如果直接点构造方法,实际上啥也看不到,这里又个技巧,这个需要在父类的构造方法中打断点!否则是看不到构造过程的,这样就可以看到,实际上它调用到了父类的默认构造器。
Enviroment体系
属性解析器,这个里面真正解析处理字符串是在一个PropertyPlaceholderHelper之中进行的。它处理的数据是存在在PropertySources这个接口之中。
属性源,对属性的封装,MutablePropertiesSources里面又一个LIst,这个List存储的就是PropertiesSource的设计。PropertySource又很多具体的实现,可以这么理解,Enviroment叫Resolver去干活,Resolver里面去找Source,在Source里面实际上存储的是Map结构。
PropertiySource的继承结构
说几个重要的PropertySource,比如MapPropertySource就是对简单的PropertySource进行了很多的扩展,这个类里面是通过map作为Source来存储属性,进行属性的读取。
Stadard的创建是使用了模板方法设计模式,子类重写了父类的方法,父类构造方法调用了子类实现的方法。
系统环境
public static final String SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME = "systemEnvironment";
系统属性
public static final String SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME = "systemProperties";
自定义属性源
@Override
protected void customizePropertySources(MutablePropertySources propertySources) {
propertySources.addLast(
new PropertiesPropertySource(SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME, getSystemProperties()));
propertySources.addLast(
new SystemEnvironmentPropertySource(SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, getSystemEnvironment()));
}
StandardServletEnvironment扩展StanrdEnvironment,这个里面对属性值进行了扩展。新增了一些PropertySource。
总结
- Environment是一个包工头,指挥Resolver干活,Resolver又指挥Helper干活,体现了分层的思想,也体现了单一职责的思想,通过组合的方式实现松耦合的效果。
- 扩展性的体现在PropertieySource这个接口以及MutablePropertiesSources,通过for循环遍历Sources去读取。
- 如果我们要管理一些属性可以怎么做呢,同样的,可以读取一个文件,然后将文件读取为map结构,放在一个MapPropertySource里面,对这个类进行扩展,就可以实现一个对属性进行自定义管理的属性类了,还是比较方便的,同样的,我们甚至可以将这个作为Environment,add到Enviroment里面的MutablePropertySources的那个List中去,这样我们甚至可以DIY的去将一些属性添加进去管理,然后如果Spring框架的API进行扩区。
- 对于设计方面的思考,单一职责,面向接口,可扩展性体现的淋漓尽致,模板方法模式等等,MutablePropertySource的设计等等都值得借鉴。