Spring 的那点事 (二) —— initPropert

这是我参与11月更文挑战的第2天,活动详情查看:2021最后一次更文挑战

功能

prepareRefresh() 该方法为 refresh() 中的一个方法。

功能为以下几点

  • 设置容器启动时间
  • 设置 closed 和 active 两个标识位
  • 初始化系统属性资源
  • 获取 Environment 对象,校验属性值并赋值到 Environment 对象中
  • 准备监听器和事件监听器

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
java复制代码package org.springframework.context.support

public abstract class AbstractApplicationContext extends DefaultResourceLoader implements ConfigurableApplicationContext, DisposableBean {

protected void prepareRefresh() {
// Switch to active.
// 设置容器启动的时间
this.startupDate = System.currentTimeMillis();
// 容器的关闭标志位
this.closed.set(false);
// 容器的激活标志位
this.active.set(true);

// 记录日志
if (logger.isDebugEnabled()) {
if (logger.isTraceEnabled()) {
logger.trace("Refreshing " + this);
}
else {
logger.debug("Refreshing " + getDisplayName());
}
}

// Initialize any placeholder property sources in the context environment.
// 留给子类覆盖,初始化属性资源
initPropertySources();

// Validate that all properties marked as required are resolvable:
// see ConfigurablePropertyResolver#setRequiredProperties
// 创建并获取环境对象,验证需要的属性文件是否都已经放入环境中
getEnvironment().validateRequiredProperties();

// Store pre-refresh ApplicationListeners...
// 判断刷新前的应用程序监听器集合是否为空,如果为空,则将监听器添加到此集合中
if (this.earlyApplicationListeners == null) {
this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
}
else {
// Reset local application listeners to pre-refresh state.
// 如果不等于空,则清空集合元素对象
this.applicationListeners.clear();
this.applicationListeners.addAll(this.earlyApplicationListeners);
}

// Allow for the collection of early ApplicationEvents,
// to be published once the multicaster is available...
// 创建刷新前的监听事件集合
this.earlyApplicationEvents = new LinkedHashSet<>();
}

protected void initPropertySources() {
}
}

扩展 initPropertySources()

Spring的强大之处不仅仅在于它为Java开发者提供了极大便利,而且在于它的开放式架构,使得用户可以拥有最大扩展 Spring 的能力。其中,initPropertySources() 方法就是一个例子。

可以看到 prepareRefresh() 中的 initPropertySources() 方法并没有任何参数,而如果进入initPropertySources() 方法内部,也会发现该方法是空的,没有任何逻辑。

Spring之所这样设计,就是为了让用户根据自己的需要,可以重写 initPropertySources() 方法,并在方法中进行个性化的属性处理以及设置。

举例

我们可以继承此类或其子类来重写initPropertySources方法,实现一些扩展。此处我们做了两个扩展:

  • 向Environment中添加了一个属性值。
  • 我们设置了一个必要的系统属性username,当Environment中不包含username属性时系统会抛出异常。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
java复制代码public class MyClassPathXmlApplicationContext extends ClassPathXmlApplicationContext {

public MyClassPathXmlApplicationContext(String... configLocations){
super(configLocations);
}

@Override
protected void initPropertySources() {
System.out.println("扩展initPropertySource");

//这里添加了一个name属性到Environment里面,以方便我们在后面用到
getEnvironment().getSystemProperties().put("name","bobo");

//这里要求Environment中必须包含username属性,如果不包含,则抛出异常
getEnvironment().setRequiredProperties("username");
}
}

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

0%