其他扩展可参考之前的文章:
1、深入理解Spring IOC之扩展篇(一)、自定义xml标签
2、深入理解Spring IOC之扩展篇(二)、BeanFactoryPostProcessor和BeanPostProcessor
3、深入理解Spring IOC之扩展篇(三)、InitializingBean、@PostConstruct、SmartInitializingSingleton
4、深入理解Spring IOC之扩展篇(四)、Aware接口
5、深入理解Spring IOC之扩展篇(五)、基于注解整合Spring框架
6、深入理解Spring IOC之扩展篇(六)、基于Aop的自定义注解
7、深入理解Spring IOC之扩展篇(七)、Spring中的event以及自定义event
我们在讲refresh方法的那篇中说到了一个prepareRefresh的方法,这个方法主要是记录容器的状态以及对环境变量的校验,我们来看看这个方法的代码:
protected void prepareRefresh() {
// 1. 记录下容器开始刷新的时间
this.startupDate = System.currentTimeMillis();
// 2. 把容器标为激活状态
synchronized (this.activeMonitor) {
this.active = true;
}
if (logger.isInfoEnabled()) {
logger.info("Refreshing " + this);
}
// 3. ClassPathXmlApplicationContext的时候调的是个空方法,跳过~
initPropertySources();
// 4. 调用StandardEnvironment中的validateRequiredProperties方法
getEnvironment().validateRequiredProperties();
}
我的注释上面写的很明确,3是个空方法,另外,我曾在正篇的第三篇中说过,4这里最后是没有做任何事情的。所以我们可以得出一个结论,在默认情况下,spring容器的启动是不依赖任何的环境变量的。如果我们想增加我们自己的校验环境变量的逻辑应该怎么做呢?这里分为两种情况,对应的做法也不相同,我们分别来看一下:
有人肯定会问自定义校验环境变量的逻辑有什么用,emmm,其实我自己觉得,这个作用还是很大的,比如,你可以让你的应用跑在对应的机器上嘛。环境变量这里的信息还是非常多的,不知道各位读者注意过没有。
第一种情况,你的项目是个普通的Spring而不是SpringBoot项目,此时我们可以这么做:
配置类,仅用作配置
@Configuration
@ComponentScan("com.example.test")
public class Config {
}
负责校验的bean
@Component
public class ConfigCheckBean implements EnvironmentAware {
private ConfigurableEnvironment environment;
@Override
public void setEnvironment(Environment environment) {
if (environment instanceof ConfigurableEnvironment){
ConfigurableEnvironment environment1 = (ConfigurableEnvironment)environment;
this.environment = environment1;
}
init();
this.environment.validateRequiredProperties();
}
private void init() {
this.environment.setRequiredProperties("aaa");
}
}
测试代码:
public static void main(String[] args) {
AnnotationConfigApplicationContext annotationConfigApplicationContext = new AnnotationConfigApplicationContext(Config.class);
}
由于我没有增加任何key为aaa的环境变量,所以此时启动当时是报错了:
第二种情况是,当你的项目是个SpringBoot项目时,我们可以这样做:
@SpringBootApplication
@MapperScan(basePackages = {"com.example.studyspringbootdemo.mybatis.mapper"})
public class StudyspringbootdemoApplication {
public static void main(String[] args) {
// 将SpringApplication中的ApplicationContext替换,然后启动
SpringApplication springBootApplication = new SpringApplication(StudyspringbootdemoApplication.class);
springBootApplication.setApplicationContextClass(MyApplicationContext.class);
springBootApplication.run();
}
// 继承SpringBoot中默认使用的AnnotationConfigServletWebServerApplicationContext并重写initPropertySources方法
public static class MyApplicationContext extends AnnotationConfigServletWebServerApplicationContext{
@Override
protected void initPropertySources() {
// 因为父类的initPropertySources并不为空,所以为了保持正常运行逻辑必须调用父类方法
super.initPropertySources();
// 添加"aaa"的校验
getEnvironment().setRequiredProperties("aaa");
}
}
}
同样的,启动会失败,因为我并没有对应环境变量: