第6节 Spring源码之 prepareRefresh 方法
Spring 容器启动核心方法:refresh()
,它内部的流程如下所示:
prepareRefresh()
方法是容器加载核心方法refresh()
方法的第一步流程,主要任务是容器刷新前的准备工作,包括以下几点:
- 设置容器的启动时间
- 设置活跃状态为true
- 设置关闭状态为false
- 获取 Environment 对象,并加载当前系统属性值到 Environment 对象中
- 准备监听器和事件的集合对象,默认空集合
一、prepareRefresh() 实现
protected void prepareRefresh() {
this.startupDate = System.currentTimeMillis();
this.closed.set(false);
this.active.set(true);
/**
* Initialize any placeholder property sources in the context environment.
* 模板方法:初始化占位符资源;spring 预留的扩展点
*/
initPropertySources();
// Validate that all properties marked as required are resolvable: see ConfigurablePropertyResolver#setRequiredProperties
// 创建并获取环境对象,验证需要的属性文件是否都已经放入到环境中
getEnvironment().validateRequiredProperties();
// 设置事件监听器集合;在 spring boot 应用启动时, applicationListeners 是有值的,但 spring 启动是没有监听器的
// 因为 spring boot 启动时默认注入了一大堆的 ApplicationListener ,它定义在 spring.factories 文件中
if (this.earlyApplicationListeners == null) {
this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
} else {
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<>();
}
prepareRefresh()
方法内部逻辑相对来说比较简单,但是也给我们预留了一些比较有意思的扩展点。
1. initPropertySources()
方法
这是一个模板方法,需要自定义子类去实现你自己的逻辑
2. validateRequiredProperties()
方法
该方法其实也是一个扩展,它的作用就是容器启动会验证你设置的环境变量或者系统变量,如果没有设置就会报错,Spring
容器启动时有系统变量:systemEnvironment
和环境变量:systemProperties
,它们在 StandardEnvironment
中定义
所以当调用
getEnvironment().validateRequiredProperties();
方法时首先是获取系统环境和环境变量:
3. initPropertySources()
和validateRequiredProperties()
扩展验证
public class CustomizeClassPathXmlApplication extends ClassPathXmlApplicationContext {
public CustomizeClassPathXmlApplication(String configLocation) {
super(configLocation);
}
@Override
protected void initPropertySources() {
// 这里定制自己的业务逻辑
System.out.println("扩展 initPropertySources");
// 设置容器启动必要参数
getEnvironment().setRequiredProperties("docker_env");
}
}
public class TestProp {
public static void main(String[] args) {
testInitPropertySources();
}
public static void testInitPropertySources() {
ApplicationContext cx = new CustomizeClassPathXmlApplication("application-bean.xml");
User user = cx.getBean("user", User.class);
System.out.println(user.getUsername());
}
}
运行结果,提示缺少属性参数:docker_env
Exception in thread "main" org.springframework.core.env.MissingRequiredPropertiesException:
The following properties were declared as required but could not be resolved: [docker_env]
一般实际业务开发使用较少,没有人真的会去强制校验。一般当你的应用程序少了某个环境变量,你启动容器也会失败,只不过这种方式只是Spring
给你提供的扩展功能而已。
转载自:https://juejin.cn/post/7245922875181400124