spring environment_Spring的Environment体系 —— Environment

我个人在阅读spring的过程中将spring 分成了几个体系,因为我觉得Spring是要给非常优秀的框架,很多设计是可以给我们复用的。比如这里讲解的Spring中的Environment体系。

Environment接口

环境主要分类为两大部分:profile,properties

42d5b1182c38ed999e02aef387b24b97.png

继承uml图如下:图片有点大而长。但是这样才详细。profile这个功能比较简单这里不介绍了。

Envirnment体系最重要的方法就是org.springframework.core.env.AbstractEnvironment#customizePropertySources 子类负责继承这个方法之后进行定制自己的 PropertySources

这里看看StandardEnvironment,超级简单。

然后我们再回来看看 AbstractEnvironment 的customizePropertySources函数

    /**     * 装饰方法模式      * Customize (定做改造) the set of {@link PropertySource} objects to be searched by this     * {@code Environment} during calls to {@link #getProperty(String)} and related     * methods.     *     * 

Subclasses that override this method are encouraged (促使) to add property

* sources using {@link MutablePropertySources#addLast(PropertySource)} such that * further subclasses may call {@code super.customizePropertySources()} with * predictable results. For example: *
* public class Level1Environment extends AbstractEnvironment { *     @Override *     protected void customizePropertySources(MutablePropertySources propertySources) { *         super.customizePropertySources(propertySources); // no-op from base class *         propertySources.addLast(new PropertySourceA(...)); *         propertySources.addLast(new PropertySourceB(...)); *     } * } * * public class Level2Environment extends Level1Environment { *     @Override *     protected void customizePropertySources(MutablePropertySources propertySources) { *         super.customizePropertySources(propertySources); // add all from superclass *         propertySources.addLast(new PropertySourceC(...)); *         propertySources.addLast(new PropertySourceD(...)); *     } * } * * * 继承链,能够像栈一样。后调用先执行。 * * * In this arrangement(约定), properties will be resolved against sources A, B, C, D in that * order. That is to say that property source "A" has precedence over property source * "D". If the {@code Level2Environment} subclass wished to give property sources C * and D higher precedence than A and B, it could simply call * {@code super.customizePropertySources} after, rather than before adding its own: *
* public class Level2Environment extends Level1Environment { *     @Override *     protected void customizePropertySources(MutablePropertySources propertySources) { *         propertySources.addLast(new PropertySourceC(...)); *         propertySources.addLast(new PropertySourceD(...)); *         super.customizePropertySources(propertySources); // add all from superclass *     } * } * * The search order is now C, D, A, B as desired. * *

Beyond these recommendations, subclasses may use any of the {@code add*},

* {@code remove}, or {@code replace} methods exposed by {@link MutablePropertySources} * in order to create the exact arrangement of property sources desired. * *

The base implementation registers no property sources.

* *

Note that clients of any {@link ConfigurableEnvironment} may further customize

* property sources via the {@link #getPropertySources()} accessor, typically within * an {@link org.springframework.context.ApplicationContextInitializer * ApplicationContextInitializer}. For example: *
* ConfigurableEnvironment env = new StandardEnvironment(); * env.getPropertySources().addLast(new PropertySourceX(...)); * * *

A warning about instance variable access

*

关于实例对象变量的警告

* * Instance variables(变量) declared in subclasses and having default initial values should * not be accessed from within this method. Due to Java object creation * lifecycle constraints, any initial value will not yet be assigned when this * callback is invoked by the {@link #AbstractEnvironment()} constructor, which may * lead to a {@code NullPointerException} or other problems. If you need to access * default values of instance variables, leave this method as a no-op and perform * property source manipulation and instance variable access directly within the * subclass constructor. Note that assigning values to instance variables is * not problematic; it is only attempting to read default values that must be avoided. * * @see MutablePropertySources * @see PropertySourcesPropertyResolver * @see org.springframework.context.ApplicationContextInitializer */ protected void customizePropertySources(MutablePropertySources propertySources) { }

上面的注解非常详细了,而且生僻的单词我都做了详细的讲解,这里就不细说了。

然后根据上面的注解就可以看看StandardEnvironment

public class StandardEnvironment extends AbstractEnvironment {    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()));}}

一个非常典型的创建环境的接口。我们在这里一般在外面直接使用StandardEnvironment (比较典型的装饰模式),怎么使用我们待会再说(先挖坑)。我们先看getSystemProperties()和getSystemEnvironment()是什么。

其中getSystemProperties()和getSystemEnvironment()是父类AbstractEnvironment的。

org.springframework.core.env.AbstractEnvironment#getSystemProperties    @Override@SuppressWarnings({"rawtypes", "unchecked"})public Map<String, Object> getSystemProperties() {    try {        return (Map) System.getProperties(); // 重点是这个方法    }    catch (AccessControlException ex) {        return (Map) new ReadOnlySystemAttributesMap() {            @Override            @Nullable            protected String getSystemAttribute(String attributeName) {                try {                    return System.getProperty(attributeName); // 重点是这个方法                }                catch (AccessControlException ex) {                    if (logger.isInfoEnabled()) {                        logger.info("Caught AccessControlException when accessing system property '" +                                    attributeName + "'; its value will be returned [null]. Reason: " + ex.getMessage());                    }                    return null;                }            }        };    }}@Override@SuppressWarnings({"rawtypes", "unchecked"})public Map<String, Object> getSystemEnvironment() {    if (suppressGetenvAccess()) {        return Collections.emptyMap();    }    try {        return (Map) System.getenv(); // 重点是这个方法    }    catch (AccessControlException ex) {        return (Map) new ReadOnlySystemAttributesMap() {            @Override            @Nullable            protected String getSystemAttribute(String attributeName) {                try {                    return System.getenv(attributeName); // 重点是这个方法                }                catch (AccessControlException ex) {                    if (logger.isInfoEnabled()) {                        logger.info("Caught AccessControlException when accessing system environment variable '" +                                    attributeName + "'; its value will be returned [null]. Reason: " + ex.getMessage());                    }                    return null;                }            }        };    }}

这里的实现很有意思,如果安全管理器阻止获取全部的系统属性,那么会尝试获取单个属性的可能性,如果还不行就抛异常了。

从上面的代码大意就是所谓的getSystemProperties()和getSystemEnvironment()其实是调用System的方法getProperties()getenv()System.getProperties() 注解如下:

public static Properties getProperties() {    SecurityManager sm = getSecurityManager();    if (sm != null) {        sm.checkPropertiesAccess();    }    return props;}

这是上面的类的说明。

1ccd4f6c367e624ee4da48fd248b130e.png

91fb12e400aa4622e6d12056984df1c3.png

getSystemEnvironment方法也是一个套路,不过最终调用的是System.getenv,可以获取jvm和OS的一些版本信息。

和 System.getenv()

public static java.util.Map<String,String> getenv() {    SecurityManager sm = getSecurityManager();    if (sm != null) {        sm.checkPermission(new RuntimePermission("getenv.*"));    }    return ProcessEnvironment.getenv();}

看明白了getSystemProperties()和getSystemEnvironment(),那么我们就要看后面的大餐

public static final String SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME = "systemEnvironment";public static final String SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME = "systemProperties";// 省略了这里不关注的代码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()));}

new PropertiesPropertySource()new SystemEnvironmentPropertySource()到底是什么鬼呢?看后面的文章!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值