仅供个人学习记录使用
来自于慕课网《图解+仿写 新手都能学懂的SpringBoot源码课》课程
Reference:全方位深入解析最新版SpringBoot源码-慕课网实战 (imooc.com)
章节目录:
一、系统初始化器介绍
二、SpringFactoriesLoader介绍
三、系统初始化器原理解析
四、总结
系统初始化器介绍
一、类名:ApplicationContextInitializer
二、介绍:Spring容器刷新之前执行的一个回调函数
三:作用:向SpringBoot容器中注册属性
四:使用:继承接口自定义实现
自定义系统初始化器:
@Order(1)
public class FirstInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext> {
@Override
public void initialize(ConfigurableApplicationContext applicationContext) {
ConfigurableEnvironment configurableEnvironment = applicationContext.getEnvironment();
Map<String, Object> map = new HashMap<>();
map.put("key1", "value1");
MapPropertySource mapPropertySource = new MapPropertySource("firstInitializer", map);
configurableEnvironment.getPropertySources().addLast(mapPropertySource);
System.out.println("run firstInitializer");
}
}
注册系统初始化器方式:
一、resources 下 META-INF 文件夹下创建 spring.factories 文件
org.springframework.context.ApplicationContextInitializer = com.mooc.sb2.initializer.FirstInitializer
二、SpringApplication addInitializers 硬编码添加
SpringApplication springApplication = new SpringApplication(Sb2Application.class);
springApplication.addInitializers(new SecondInitializer());
springApplication.run(args);
三、在resources 下 application.properties 文件中注册
context.initializer.classes = com.mooc.sb2.initializer.ThirdInitializer
Tips:
-
都要实现 ApplicationContextInitializer 接口
-
order 值越小越先执行
-
application.properties 中定义的优先于其他方式
SpringFactoriesLoader 介绍
-
框架内部使用的通用工厂加载机制
-
从 classpath 下多个 jar 包特定的位置读取文件并初始化类
-
文件内容必须是kv形势,即 properties 类型
-
key 是全限定名(抽象类|接口)、value 是实现,多个实现用“,”分隔
源码部分
private <T> Collection<T> getSpringFactoriesInstances(Class<T> type, Class<?>[] parameterTypes, Object... args) {
// 获取类加载器
ClassLoader classLoader = getClassLoader();
// 获取系统初始化器名称
Set<String> names = new LinkedHashSet<>(SpringFactoriesLoader.loadFactoryNames(type, classLoader));
// 获取系统初始化器实例
List<T> instances = createSpringFactoriesInstances(type, parameterTypes, classLoader, args, names);
// 给系统初始化器实例排序
AnnotationAwareOrderComparator.sort(instances);
return instances;
}
获取系统初始化器名称:
获取系统初始化器实例:
获取全限定类名、获取构造器、通过 BeanUtils 与构造器获取实例
SpringFactoriesLoader 作用
- SpringBoot 框架中从类路径 jar 包中读取特定文件实现扩展类的载入
loadFactories流程
SpringApplicationInitializer
-
上下文刷新即 refresh 方法前调用
-
用来编码设置一些属性变量通常用在 web 环境中
-
可以通过 order 接口进行排序
SpringApplicationInitializer 调用流程
为何 thirdInitializer 先执行?
DelegatingApplicationContextInitializer order 为0,优先执行
调用流程
实现原理:
-
定义在 spring.factories 文件中被 SpringFactoriesLoader 发现注册
-
SpringApplication 初始化完毕后手动添加
-
定义成环境变量被 DelegatingApplicationContextInitializer 发现注册