参考源
《Spring源码深度解析(第2版)》
版本
本文章基于 Spring 5.3.15
Spring IOC 的核心是
其中一共有 13 个主要方法,这里分析第 1 个:AbstractApplicationContext
的refresh
方法。prepareRefresh
。
1 AbstractApplicationContext
1-1 刷新前的准备工作
prepareRefresh()
/** * 1 刷新前的准备工作 * 设置容器的启动时间 * 设置关闭状态为 false * 设置活跃状态为 true * 获取 Environment 对象,并加载当前系统的属性值到 Environment 对象中并进行验证 * 准备监听器和事件的集合对象,默认为空的集合 */protected void prepareRefresh() { // 设置容器启动时间 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()); } } // 留给子类覆盖,初始化属性资源 initPropertySources(); // 获取环境对象 // 验证需要的属性文件是否都已经放入环境中 getEnvironment().validateRequiredProperties(); // 判断刷新前的应用程序监听器集合是否为空,如果为空,则将监听器添加到此集合中 if (this.earlyApplicationListeners == null) { // 这里 this.applicationListeners 为空,SpringBoot 中则有值 this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners); } else { // 如果不等于空,则清空集合元素对象 this.applicationListeners.clear(); this.applicationListeners.addAll(this.earlyApplicationListeners); } // 创建刷新前的监听事件集合 this.earlyApplicationEvents = new LinkedHashSet<>();}
1-2 初始化属性资源
initPropertySources()
protected void initPropertySources() { }
这里该方法为空,是为了留给子类扩展使用。
扩展
添加必需属性验证
如果在使用 Spring 容器时某些属性是必需的,可以用扩展 initPropertySources()
的方式实现验证。
编写自定义类继承
ClassPathXmlApplicationContext
public class MyClassPathXmlApplicationContext extends ClassPathXmlApplicationContext { public MyClassPathXmlApplicationContext(String... configLocations) { super(configLocations); } @Override protected void initPropertySources() { System.out.println("扩展了initPropertySources"); // 添加验证要求 getEnvironment().setRequiredProperties("VAR"); }}
使用自定义类
ApplicationContext context = new MyClassPathXmlApplicationContext("applicationContext.xml");UserDao userDao = context.getBean(UserDao.class);userDao.add();
运行结果
因为添加了 VAR 为必需属性,而环境中找不到该属性,所以报错。
1-2 获取环境信息
getEnvironment()
public ConfigurableEnvironment getEnvironment() { if (this.environment == null) { // 创建环境对象 this.environment = createEnvironment(); } return this.environment;}
由于前面对 environment
赋值了,这里就直接返回 environment
。
1 AbstractApplicationContext
1-2 验证必需的属性
validateRequiredProperties()
2 AbstractEnvironment
public void validateRequiredProperties() throws MissingRequiredPropertiesException { // 验证必需的属性 this.propertyResolver.validateRequiredProperties();}
3 AbstractPropertyResolver
public void validateRequiredProperties() { MissingRequiredPropertiesException ex = new MissingRequiredPropertiesException(); for (String key : this.requiredProperties) { if (this.getProperty(key) == null) { ex.addMissingRequiredProperty(key); } } if (!ex.getMissingRequiredProperties().isEmpty()) { throw ex; }}
这里主要对必需的属性做验证,没有则抛出对应异常。
public class MissingRequiredPropertiesException extends IllegalStateException { @Override public String getMessage() { return "The following properties were declared as required but could not be resolved: " + getMissingRequiredProperties(); }}
这里抛出的
由此可见,刚才的异常正是由这里抛出的。MissingRequiredProperty
异常内容正对应了前面示例中报的异常