有人辞官归故里
有人星夜赶科考
前途似海来日方长。
实现ApplicationContextInitializer接口
@Order(1)
public class FirstInitializer implements ApplicationContextInitializer {
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
//获取环境
ConfigurableEnvironment environment = applicationContext.getEnvironment();
HashMap<String, Object> map = new HashMap<>();
map.put("key1","value1");
MapPropertySource mapPropertySource = new MapPropertySource("firstInitializer",map);
environment.getPropertySources().addLast(mapPropertySource);
System.out.println("run firstInitializer");
}
}
spring.factories内填写接口实现
key值为org.springframework.context.ApplicationContextInitializer
org.springframework.context.ApplicationContextInitializer=cn.test.initializer.FirstInitializer
实现ApplicationContextInitializer接口
@Order(2)
public class SecondInitializer implements ApplicationContextInitializer {
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
//获取环境
ConfigurableEnvironment environment = applicationContext.getEnvironment();
HashMap<String, Object> map = new HashMap<>();
map.put("key2","value2");
MapPropertySource mapPropertySource = new MapPropertySource("secondInitializer",map);
environment.getPropertySources().addLast(mapPropertySource);
System.out.println("run secondInitializer");
}
}
SpringApplication类初始化后设置进去(启动类)
@SpringBootApplication
public class Springboot2Application {
public static void main(String[] args) {
// SpringApplication.run(Springboot2Application.class, args);
SpringApplication springApplication = new SpringApplication(Springboot2Application.class);
springApplication.addInitializers(new SecondInitializer());
springApplication.run(args);
}
}
实现ApplicationContextInitializer接口
@Order(3)
public class ThirdInitializer implements ApplicationContextInitializer {
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
//获取环境
ConfigurableEnvironment environment = applicationContext.getEnvironment();
HashMap<String, Object> map = new HashMap<>();
map.put("key3","value3");
MapPropertySource mapPropertySource = new MapPropertySource("thridInitializer",map);
environment.getPropertySources().addLast(mapPropertySource);
System.out.println("run thridInitializer");
}
}
application.properties配置文件内填写接口实现
key值为context.initializer.classes
context.initializer.classes=cn.test.initializer.ThirdInitializer
@Autowired
private Environment environment;
@RequestMapping("test2")
public String test2(){
return environment.getProperty("key3");
}
@Service
public class DemoService implements ApplicationContextAware {
private ApplicationContext applicationContext;
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
this.applicationContext=applicationContext;
}
//调用test方法获取
public String test(){
return applicationContext.getEnvironment().getProperty("key3");
}
}
这个DelegatingApplicationListener会在系统初始化的时候调用getListeners()方法加载properties配置文件的值。
从run方法进去
获取SpringFactories实例化对象,参数是ApplicationContextInitializer
这也是我们注册系统初始化器必须的步骤
实现ApplicationContextInitializer接口
加载FactoryName
查缓存,缓存没有,则从文件读取,并加入缓存。
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
ClassLoader classLoader = getClassLoader();
//使用名称并确保唯一以防止重复
//加载FactoryName,结果保存到Set集合,确保结果唯一
Set<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
//获取实例化对象
List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
//按照Order排序,为了按照优先级加载
AnnotationAwareOrderComparator.sort(instances);
return instances;
}
Springboot框架中从类路径jar包中读取特定文件实现扩展类的载入。
文章持续更新,可以微信搜索「 绅堂Style 」第一时间阅读,回复【资料】有我准备的面试题笔记。
GitHub https://github.com/dtt11111/Nodes 有总结面试完整考点、资料以及我的系列文章。欢迎Star。