Spring系列-1.1 Environment解析
Spring版本:Spring 5.2.9.BUILD-SNAPSHOT
修改过部分源码,但不影响主体流程
Environment简介#
Environment是Spring核心框架中定义的一个接口,用来表示整个应用运行时的环境,主要管理应用程序两个方面的内容:profile
和 property
。
profile#
一个profile是一组Bean definition
的逻辑分组。profile可以简单的等同于环境,比如说平时项目中常见的环境有开发(dev
)、测试(stg
)和生产(prod
),Spring 启动的时候可以设置激活具体的环境。
property#
一个应用的属性有很多来源: 属性文件(properties files),JVM系统属性,系统环境变量,JNDI,servlet上下文参数,临时属性对象等。
获取Environment#
如果想直接使用Environment
对象访问profile
状态或者获取属性,可以有两种方式
-
实现EnvironmentAware接口
-
@Autowired注入一个
Environment
对象
但是基本不这么做,大部分都是通过@Value
注解或者在xml
配置文件中使用${}
进行获取。
继承关系#
接口/类 |
说明 |
---|---|
PropertyResolver |
接口,抽象对属性源的访问,比如是否包含某个属性,读取属性,解析占位符,将读取到的属性转换成指定类型 |
Environment |
继承自PropertyResolver ,对环境属性访问和default/active profile 访问的抽象因为继承自PropertyResolver ,所以它自然具备PropertyResolver 提供的所有能力,对环境属性的访问也正是通过PropertyResolver 定义的这些能力 |
ConfigurablePropertyResolver |
为PropertyResolver 接口抽象的属性源访问做了配置方面的增强。比如设置将属性值转换工具,指定占位符前缀后缀 |
ConfigurableEnvironment |
在所继承的接口之上增加了设置defaut/active profile 的能力,增加/删除环境对象中属性源的能力 |
ConfigurableWebEnvironment |
向接口ConfigurableEnvironment 增强了根据Servlet 上下文/配置初始化属性源的能力 |
AbstractEnvironment |
Environment 抽象基类,实现了ConfigurableEnvironment |
StandardEnvironment |
针对标准Spring 应用的环境,在AbstractEnvironment 基础上提供了属性源systemEnvironment 和systemProperties |
StandardServletEnvironment |
针对标准Spring Servlet Web 应用的环境,在StandardEnvironment的基础上增加了servletContextInitParams/servletConfigInitParams/jndiProperties 三个属性源 |
源码解析#
入口#
public ClassPathXmlApplicationContext(
String[] configLocations, boolean refresh, @Nullable ApplicationContext parent) throws BeansException {
// 调用父类构造方法,进行相关的对象创建等操作,包含属性的赋值操作
// 初始化成员属性
super(parent);
//设置应用程序上下文的配置路径
setConfigLocations(configLocations);
if (refresh) {
refresh();
}
}
-
调用
super(parent)
方法进行相关的对象创建等操作 -
setConfigLocations(configLocations);用于设置配置文件的路径,并处理占位符。
setConfigLocations(configLocations)#
/**
* 设置应用程序上下文的配置路径
*
* Set the config locations for this application context.
* <p>If not set, the implementation may use a default as appropriate.
*/
public void setConfigLocations(@Nullable String... locations) {
if (locations != null) {
Assert.noNullElements(locations, "Config locations must not be null");
this.configLocations = new String[locations.length];
for (int i = 0; i < locations.length; i++) {
// 解析给定路径
// 处理占位符 spring-${username}.xml
this.configLocations[i] = resolvePath(locations[i]).trim();
}
}
else {
this.configLocations = null;
}
}
resolvePath(String path)#
protected String resolvePath(String path) {
return getEnvironment().resolveRequiredPlaceholders(path);
}
getEnvironment()#
@Override
public ConfigurableEnvironment getEnvironment() {
if (this.environment == null) {
this.environment = createEnvironment();
}
return this.environment;
}
createEnvironment()#
protected ConfigurableEnvironment createEnvironment() {
return new StandardEnvironment();
}
- 此时会调用父类的构造方法,父类的构造方法会调到自己实现的
customizePropertySources(this.propertySources)
;
@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()));
}
- 此时已经读到系统的相关环境配置信息
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)