AnnotationConfigApplicationContext-prepareRefresh
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();
// Allow for the collection of early ApplicationEvents,
// to be published once the multicaster is available...
// 保存容器中的一些早期的事件
this.earlyApplicationEvents = new LinkedHashSet<ApplicationEvent>();
}
initPropertySources
发现这个方法为空方法,是用来留给子类进行属性值处理的
protected void initPropertySources() {
// For subclasses: do nothing by default.
}
getEnvironment()
@Override
public ConfigurableEnvironment getEnvironment() {
if (this.environment == null) {
this.environment = createEnvironment();
}
return this.environment;
}
createEnvironment
protected ConfigurableEnvironment createEnvironment() {
return new StandardEnvironment();
}
StandardEnvironment继承了AbstractEnvironment,重写了customizePropertySources
public class StandardEnvironment extends AbstractEnvironment {
public static final String SYSTEM_ENVIRONMENT_PROPERTY_SOURCE_NAME = "systemEnvironment";
public static final String SYSTEM_PROPERTIES_PROPERTY_SOURCE_NAME = "systemProperties";
public StandardEnvironment() {
}
protected void customizePropertySources(MutablePropertySources propertySources) {
propertySources.addLast(new MapPropertySource("systemProperties", this.getSystemProperties()));
propertySources.addLast(new SystemEnvironmentPropertySource("systemEnvironment", this.getSystemEnvironment()));
}
}
getEnvironment().validateRequiredProperties()
来看看getEnvironment().validateRequiredProperties()的源码,对应的是AbstractPropertyResolver类的validateRequiredProperties方法:
public void validateRequiredProperties() {
MissingRequiredPropertiesException ex = new MissingRequiredPropertiesException();
Iterator var2 = this.requiredProperties.iterator();
while(var2.hasNext()) {
String key = (String)var2.next();
if (this.getProperty(key) == null) {
ex.addMissingRequiredProperty(key);
}
}
if (!ex.getMissingRequiredProperties().isEmpty()) {
throw ex;
}
}
可见spring容器初始化的时候,会从集合requiredProperties中取出所有key,然后获取这些key的环境变量(包括系统环境变量和进程环境变量),如果有一个key对应的环境变量为空,就会抛出异常,导致spring容器初始化失败;
实现自定义环境变量验证
发现在多种ApplicationContext中只有WebApplicationContext相关的,才可以重写initPropertySources
自定义ApplicationContext
/**
* @Description : AnnotationConfigServletWebServerApplicationContext,重写了initPropertySources方法,
* 要求spring启动的时候环境变量MYSQL_HOST必须存在
* @Author : zq2599@gmail.com
* @Date : 2018-08-10 21:40
*/
public class CustomApplicationContext extends AnnotationConfigServletWebServerApplicationContext {
@Override
protected void initPropertySources() {
super.initPropertySources();
//把"MYSQL_HOST"作为启动的时候必须验证的环境变量
getEnvironment().setRequiredProperties("MYSQL_HOST");
}
}
创建应用启动类
创建应用启动类CustomizepropertyverifyApplication,指定ApplicationContext的class为CustomApplicationContext:
@SpringBootApplication
public class CustomizepropertyverifyApplication {
public static void main(String[] args) {
SpringApplication springApplication = new SpringApplication(CustomizepropertyverifyApplication.class);
springApplication.setApplicationContextClass(CustomApplicationContext.class);
springApplication.run(args);
}
}
运行结果
org.springframework.core.env.MissingRequiredPropertiesException: The following properties were declared as required but could not be resolved: [MYSQL_HOST]
at org.springframework.core.env.AbstractPropertyResolver.validateRequiredProperties(AbstractPropertyResolver.java:146) ~[spring-core-5.0.8.RELEASE.jar:5.0.8.RELEASE]
at org.springframework.core.env.AbstractEnvironment.validateRequiredProperties(AbstractEnvironment.java:519) ~[spring-core-5.0.8.RELEASE.jar:5.0.8.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.prepareRefresh(AbstractApplicationContext.java:591) ~[spring-context-4.3.12.RELEASE.jar:4.3.12.RELEASE]
at org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext.prepareRefresh(AnnotationConfigServletWebServerApplicationContext.java:200) ~[spring-boot-2.0.4.RELEASE.jar:2.0.4.RELEASE]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:512) ~[spring-context-4.3.12.RELEASE.jar:4.3.12.RELEASE]
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:140) ~[spring-boot-2.0.4.RELEASE.jar:2.0.4.RELEASE]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:762) ~[spring-boot-2.0.4.RELEASE.jar:2.0.4.RELEASE]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:398) ~[spring-boot-2.0.4.RELEASE.jar:2.0.4.RELEASE]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:330) ~[spring-boot-2.0.4.RELEASE.jar:2.0.4.RELEASE]
at com.atguigu.CustomizepropertyverifyApplication.main(CustomizepropertyverifyApplication.java:18) [classes/:na]