Spring源码(四):Spring运行环境Environment

Spring运行环境

Spring在创建容器时,会创建Environment环境对象,用于保存spring应用程序的运行环境相关的信息。在创建环境时,需要创建属性源属性解析器,会解析属性值中的占位符,并进行替换。

创建环境时,会通过System.getProperties()获取JVM系统属性,会通过System.getenv()获取JVM环境属性。

Environment在Spring中的使用

spring在创建容器时需要指定需要加载配置文件路径,在加载配置文件路径时,需要解析字符串中的占位符。解析占位符时,需要环境信息,此时会创建一个标准的spring运行环境,即创建StandardEnvironment对象。
1、调用setConfigLocations方法给spring设置需要加载的配置文件的路径,源码如下:

// 将配置文件的路径放到configLocations 字符串数组中
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++) {
			//解析路径,将解析的路径存放到字符串数组中
			this.configLocations[i] = resolvePath(locations[i]).trim();
		}
	}
	else {
		this.configLocations = null;
	}
}

2、调用resolvePath方法解析配置文件路径中的占位符,源码如下:

// 解析给定的路径,必要时用相应的环境属性值替换占位符。应用于配置位置。
protected String resolvePath(String path) {
	// 获取环境,解决所需的占位符
	return getEnvironment().resolveRequiredPlaceholders(path);
}

3、调用getEnvironment方法获取环境信息,如果没有指定spring的环境信息,通过createEnvironment获取默认的环境,也就是spring的标准环境。getEnvironment方法源码如下:

// 获取spring的环境信息,如果没有指定,获取到的时默认的环境
@Override
public ConfigurableEnvironment getEnvironment() {
	if (this.environment == null) {
		this.environment = createEnvironment();
	}
	return this.environment;
}

4、调用createEnvironment方法获取默认的环境(spring的标准环境),使用StandardEnvironment无参构造创建对象。源码如下:

// 获取默认的环境
protected ConfigurableEnvironment createEnvironment() {
	return new StandardEnvironment();
}

Spring的标准环境StandardEnvironment

Spring的标准环境StandardEnvironment适合在非web应用程序中使用。

在AbstractApplicationContext类的createEnvironment方法中会调用StandardEnvironment的无参构造方法创建环境对象。
1、调用StandardEnvironment的无参构造方法,该方法中没有任何逻辑处理,源码如下:

public StandardEnvironment() {}

2、StandardEnvironment类是AbstractEnvironment抽象类的子类,因此使用StandardEnvironment的无参构造创建对象时会调用父类AbstractEnvironment的无参构造方法。AbstractEnvironment在下文中有描述。

3、重写AbstractEnvironment类中的customizePropertySources方法,用于设置属性源,该方法通过父类进行回调。
该方法会获取JVM系统属性和环境属性并设置到MutablePropertySources类中存放属性源的CopyOnWriteArrayList中。
1)JVM系统属性通过System.getProperties()获取;
2)环境属性通过System.getenv()获取。
StandardEnvironment类中customizePropertySources方法源码如下:

// 设置属性源,JVM系统属性中的属性将优先于环境属性中的属性。
@Override
protected void customizePropertySources(MutablePropertySources propertySources) {
	/**
	 * 1、MutablePropertySources类中使用CopyOnWriteArrayList存储属性源,集合中存储PropertySource的子类
	 * 2、PropertiesPropertySource是PropertySource的子类,PropertySource类中有三个成员变量
	 * 		1)logger:日志对象
	 * 		2)name:用来保存属性源名称
	 * 		3)source:用来保存属性源中的属性
	 */
	// getSystemProperties():通过System.getProperties()获取JVM属性键值对,并转成Map
	propertySources.addLast(
			new PropertiesPropertySource(SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME, getSystemProperties()));
	// getSystemEnvironment():通过System.getenv()获取环境属性键值对,并撰成Map
	propertySources.addLast(
			new SystemEnvironmentPropertySource(SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME, getSystemEnvironment()));
}

4、StandardEnvironment类中设置了两个静态常量:
1)systemEnvironment:以系统环境为属性源
2)systemProperties:以JVM系统属性为属性源

/** System environment property source name: {@value}.
 * 系统环境属性源名:{@value}。 */
public static final String SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME = "systemEnvironment";

/** JVM system properties property source name: {@value}.
 * JVM系统属性属性源名称:{@value}。*/
public static final String SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME = "systemProperties";

Spring的抽象环境AbstractEnvironment

StandardEnvironment类是AbstractEnvironment抽象类的子类,因此使用StandardEnvironment的无参构造创建对象时会调用父类AbstractEnvironment的无参构造方法。

1、AbstractEnvironment的无参构造方法,该方法会调用AbstractEnvironment的有参构造方法,源码如下:

public AbstractEnvironment() {
	this(new MutablePropertySources());
}

2、AbstractEnvironment的有参构造
该方法的主要做三件事:
1)给成员变量赋值
2)创建属性源属性解析器
3)调用子类重写的customizePropertySources方法(方法回调)。虽然方法回调在成员变量的赋值之后,但由于是引用传递,所以通过成员属性可以获取到改变之后的值。

// 使用了模板方法设计模式。
// 给成员变量赋值,并调用子类重写的方法,对propertySources进行操作。
protected AbstractEnvironment(MutablePropertySources propertySources) {
	// 给全局变量 可变属性源 赋值
	this.propertySources = propertySources;
	// 创建属性解析器:PropertySourcesPropertyResolver 属性源属性解析器
	this.propertyResolver = createPropertyResolver(propertySources);
	// 自定义属性源,此处回调子类重写的方法。子类通过重写该方法可以操作propertySources。spring标准环境StandardEnvironment重写了该方法
	customizePropertySources(propertySources);
}

3、调用createPropertyResolver创建属性解析器,用于解析属性值中的占位符并进行替换。

// 在创建环境时,需要创建属性解析器
protected ConfigurablePropertyResolver createPropertyResolver(MutablePropertySources propertySources) {
	return new PropertySourcesPropertyResolver(propertySources);
}

4、AbstractEnvironment的成员属性

// 指示Spring忽略系统环境变量,默认值为"false"。
// false表示不会忽略系统环境变量,此时getSystemEnvironment方法会调用System.getenv()获取环境属性
// true表示会忽略系统的环境变量,此时getSystemEnvironment方法会返回一个空的Map
public static final String IGNORE_GETENV_PROPERTY_NAME = "spring.getenv.ignore";

// 指定系统启动时使用哪些配置文件,可以使用逗号隔开
public static final String ACTIVE_PROFILES_PROPERTY_NAME = "spring.profiles.active";

// 指定系统启动时使用默认的配置文件,可以使用逗号隔开
public static final String DEFAULT_PROFILES_PROPERTY_NAME = "spring.profiles.default";

// 保留的默认的配置文件的名称,如果没有显式设置默认配置文件名称,也没有显式设置活动配置文件名称,则默认情况下该配置文件将自动激活。
protected static final String RESERVED_DEFAULT_PROFILE_NAME = "default";

// 日志对象
protected final Log logger = LogFactory.getLog(getClass());

//系统启动时使用的配置文件
private final Set<String> activeProfiles = new LinkedHashSet<>();

// 默认配置文件
private final Set<String> defaultProfiles = new LinkedHashSet<>(getReservedDefaultProfiles());

// 可变属性源,使用该成员变量保存属性源及通过该属性源获取的属性
private final MutablePropertySources propertySources;

// 可配置的属性解析器
private final ConfigurablePropertyResolver propertyResolver;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring AOP中,拦截器责任链处理过程是指当目标方法被多个通知匹配到时,Spring通过引入拦截器链来保证每个通知的正常执行。拦截器链是由一系列的拦截器组成的,每个拦截器都负责在目标方法的前后执行特定的逻辑。 在源码中,拦截器责任链的处理过程主要通过MethodInvocation接口来实现。MethodInvocation接口提供了proceed()方法,用于执行拦截器链中下一个拦截器的逻辑。当调用proceed()方法时,会按照拦截器链的顺序依次执行每个拦截器的逻辑,直到达到链的末尾或者某个拦截器决定终止链的执行。 在拦截器责任链处理过程中,每个拦截器可以在目标方法的调用前后执行自定义的逻辑。拦截器可以对方法的参数进行检查、修改方法的返回值,或者在方法执行前后记录日志等操作。通过拦截器责任链的处理,Spring AOP能够实现面向切面编程的功能。 需要注意的是,拦截器链的执行顺序是根据拦截器的配置顺序确定的。在Spring的配置文件中,可以通过配置拦截器的顺序来控制拦截器链的执行顺序。这样可以确保每个拦截器按照预期的顺序执行,从而达到期望的功能效果。 总结起来,Spring AOP源码的拦截器责任链处理过程主要通过MethodInvocation接口实现,它通过调用proceed()方法来依次执行拦截器链中每个拦截器的逻辑。拦截器链的执行顺序可以通过配置文件来控制,从而实现面向切面编程的功能。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [Spring AOP源码:拦截器责任链处理过程](https://blog.csdn.net/weixin_45031612/article/details/128806966)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [Spring AOP 自动代理源码 DefaultAdvisorAutoProxyCreator](https://download.csdn.net/download/weixin_38530536/14854229)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [【SpringSpring AOP 源码分析-拦截器链的执行过程()](https://blog.csdn.net/qq_46514118/article/details/121912507)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值