1、Spring Boot 系统初始化器
系统初始化器介绍
SpringFactoriesLoader介绍
系统初始化器原理
2、系统初始化器介绍
类名: ApplicationContextinitializer
介绍: Spring容量刷新之前执行的一个回调函数
作用: 向SpringBoot容器中注册属性
使用:继承接口自定义实现
3、系统初始化器实践
创建系统初始化器方式一(实现原理:定义在spring.factories 文件中被SpringFactoriesLoader发现注册)
1)创建初始化器
在包initializer下创建FirstInitializer
/** * * 第一个系统初始化器 */ @Order(1) public class FirstInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> { @Override public void initialize(ConfigurableApplicationContext applicationContext) { ConfigurableEnvironment environment = applicationContext.getEnvironment(); 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"); } }
2) 创建spring.factories
内容为:
org.springframework.context.ApplicationContextInitializer=com.example.demo.initialize.FirstInitializer
3) 创建服务类 TestService
@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("key1"); } }
4) 在Controller层增加方法
@RequestMapping("/test") @ResponseBody public String test(){ return testService.test(); }
5) 启动工程查看效果
可以发现打印了run FirstInitializer
然后调用接口。返回值为之前设置的value1
创建系统初始化器方式二(实现原理:初始化完毕手动添加)
1)订单创建初始化器
@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"); } }
2) SB2Application改成如下
@SpringBootApplication @MapperScan("com.example.demo.mapper") public class Sb2Application { public static void main(String[] args) { //SpringApplication.run(Sb2Application.class, args); SpringApplication springApplication = new SpringApplication(Sb2Application.class); springApplication.addInitializers(new SecondInitializer()); springApplication.run(args); } }
3) 修改Service的test方法
public String test(){ return applicationContext.getEnvironment().getProperty("key2"); }
4)启动(说明两个初始化器都已经创建)
. ____ _ __ _ _
/\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
\\/ ___)| |_)| | | | | || (_| | ) ) ) )
' |____| .__|_| |_|_| |_\__, | / / / /
=========|_|==============|___/=/_/_/_/
:: Spring Boot :: (v2.1.6.RELEASE)
run FirstInitializer
run SecondInitializer
5)、测试返回结果。返回value2
创建系统初始化器方式三(实现原理:定义成环境变量被DelegatingApplicationContextInitializer发现注册)
1)创建初始化器
@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"); } }
2) 在application.properties 增加
context.initializer.classes=com.example.demo.initializer.ThirdInitializer
3)、修改TestServer的test方法
public String test(){ return applicationContext.getEnvironment().getProperty("key3"); }
4) 启动测试
可以发现打印的顺序和定义的不一致。第三个ThirdInitializer初始化器优先于第一个和第二个打印出来。
使用接口测试,返回value2
那springboot初始化器是如何被识别呢,靠的就是SpringFactoriesLoader
springboot初始化器原理:
初始化SpringApplication 工厂加载机制 SpringFactoriesLoader
调用run方法: Spring Boot 系统初始化器是如何被调用的,以及实现原理
作者:Work Hard Work Smart
出处:http://www.cnblogs.com/linlf03/
欢迎任何形式的转载,未经作者同意,请保留此段声明!