我们在讲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"); } } }
同样的,启动会失败,因为我并没有对应环境变量: