关于扩展
- 在之前学习spring环境初始化源码的过程中,见到有些地方能通过子类来实现自定义扩展,从本章开始,我们来逐个实践这些扩展,除了加深对spring的理解,有的扩展也能解决一些通用的问题;
- 文中涉及的spring版本号为4.1.8.RELEASE;
扩展功能介绍
- 今天实战的内容,是通过spring容器来确保环境变量MYSQL_HOST一定存在,如果不存在应用就会启动失败;
分析spring源码
- 通过分析spring源码来确定如何扩展;
- 在spring环境初始化的时候,AbstractApplicationContext的prepareRefresh方法会被调用,源码如下
protected void prepareRefresh() {
this.startupDate = System.currentTimeMillis();
this.closed.set(false);
this.active.set(true);
if (logger.isInfoEnabled()) {
logger.info("Refreshing " + this);
}
// Initialize any placeholder property sources in the context environment
initPropertySources();
// Validate that all properties marked as required are resolvable
// see ConfigurablePropertyResolver#setRequiredProperties
getEnvironment().validateRequiredProperties();
}
- initPropertySources是个空方法,留给子类扩展;
- 来看看getEnvironment().validateRequiredProperties()的源码,对应的是AbstractPropertyResolver类的validateRequiredProperties方法:
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;
}
}
- 可见spring容器初始化的时候,会从集合requiredProperties中取出所有key,然后获取这些key的环境变量(包括系统环境变量和进程环境变量),如果有一个key对应的环境变量为空,就会抛出异常,导致spring容器初始化失败;
扩展功能分析
- 看了AbstractPropertyResolver类的validateRequiredProperties方法源码后,可以确定该方法能强制要求一些环境变量必须存在,否则停止spring启动,我们只要把我们认为必要的环境变量的key存入集合requiredProperties中即可,达到此目标需要解决下面两个问题:
- 如何将环境变量的key存入集合requiredProperties?
调用AbstractPropertyResolver类的setRequiredProperties方法,注意该方法是向集合requiredProperties中添加数据,并不会将已有数据清除;
- 在什么时候执行AbstractPropertyResolver类的setRequiredProperties方法设置key?
创建一个
AbstractApplicationContext的子类,重写initPropertySources方法,在此方法中执行AbstractPropertyResolver类的setRequiredProperties;
开始实战
- 用maven创建一个SpringBoot工程,工程名为customizepropertyverify,pom.xml内容如下:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.bolingcavalry</groupId>
<artifactId>customizepropertyverify</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>customizepropertyverify</name>
<description>Demo project for Spring Boot</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.ve