SpringBoot系统初始化器
一、实现初始化器的3中方法
我们在项目目录下建立目录initializer。实现初始化器我们需要去继承ApplicationContextInitializer接口,并且重写initialize方法。
在这个目录下我们建立我们的initializer,然后再用三种方法去初始化它。
方式1:在initializer下建立FirstInitializer.java文件,在spring.factories配置文件中去初始化,内容如下。
@Order(1)
public class FirstInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
ConfigurableEnvironment environment = applicationContext.getEnvironment();
environment.setRequiredProperties("mooc");
Map<String, Object> map = new HashMap<>();
map.put("key1", "value1");
MapPropertySource mapPropertySource = new MapPropertySource("firstInitializer", map);
environment.getPropertySources().addLast(mapPropertySource);
System.out.println("run firstInitializer");
}
}
接着我们在resources目录下建立META-INF文件夹,并在其中建立文件 spring.factories,这个文件是我们用来初始化FirstInitializer。
内容:
org.springframework.context.ApplicationContextInitializer=com.mooc.sb2.initializer.FirstInitializer
方式2:在initializer下建立SecondInitializer.java文件,改写项目启动类方法,在启动类中初始化,内容如下。
@Order(2)
public class SecondInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
ConfigurableEnvironment environment = applicationContext.getEnvironment();
Map<String, Object> map = new HashMap<>();
map.put("key2", "value2");
MapPropertySource mapPropertySource = new MapPropertySource("secondInitializer", map);
environment.getPropertySources().addLast(mapPropertySource);
System.out.println("run secondInitializer");
}
}
然后我们改写springboot的启动类Sb2Application.class代码,在启动方法中去初始化。
public class Sb2Application {
public static void mian (String[] args) {
SpringApplication springApplication = new SpringApplication(Sb2Application.class);
springApplication.addInitializers(new SecondInitializer());
springApplication.run(args);
}
}
方法3:建立ThirdInitializer.java文件,我们在application.properties配置文件中初始化。
@Order(3)
public class ThirdInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
ConfigurableEnvironment environment = applicationContext.getEnvironment();
Map<String, Object> map = new HashMap<>();
map.put("key3", "value3");
MapPropertySource mapPropertySource = new MapPropertySource("thirdInitializer", map);
environment.getPropertySources().addLast(mapPropertySource);
System.out.println("run thirdInitializer");
}
}
application.properties文件中添加:
context.initializer.classes=com.mooc.sb2.initializer.Thirdinitializer
以上就是我们实现三种初始化的方法。可以进行测试。
二、验证自定义的初始化器
编写service类和controller类去获取上下文,得到我们初始化器中初始化的内容。其中获取的property名字可以是:key1、key2或key3,对应着三种初始化的方式代码。
service层实现:
@Component
public class TestService implements ApplicationContextAware {
private ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext = applicationContext;
}
public String test() {
return applicationContext.getEnvironment().getProperty("key3");
}
}
controller层实现:
@Controller
@RequestMapping("/demo")
public class DemoController {
@Autowired
private TestService testService;
@RequestMapping("test")
@ResponseBody
public String test() {
return testService.test();
}
}
我们启动springboot后在浏览器端输入localhost:8080/demo/test,就会出现value1、value2或value3,那么就初始化成功。
三、3种初始化实现方式注意点
- 都要实现ApplicationContextInitializer接口;
- Order值越小越先执行;
- application.properties中定义的优先于其它方式;
四、面试问题
1.介绍SpringFactoriesLoader ?
springboot工厂的加载类,springboot用它来完成扩展点实现的展露。
2.SpringFactoriesLoader如何加载工厂类?
通过读取指定路径下的指定文件,把他们读取成一个Property对象,然后依次去遍历文件内容,组装成类名和对象实现,通过order进行排序。
3.系统初始化器的作用?
是springboot容器的回调接口,通过它向springboot容器中定义属性。
4.系统初始化器调用时机?
在springboot的run方法中调用的。
5.如何自定义实现系统初始化器?
文章上面三种方法。
6.自定义初始化器有哪些注意事项?
order值的排序问题,以及不同的初始化实现方法让order值失效(比如pplication.properties中定义的优先于其它方式;)。