一起学习springboot源码(系统初始化器)
Posted sirius-sen
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一起学习springboot源码(系统初始化器)相关的知识,希望对你有一定的参考价值。
一、介绍
在初始化过程中,会进行配置系统初始化器
1、类名:ApplicationContextInitializer
2、介绍:他是spring容器刷新之前执行的一个回调函数
3、作用:向springboot容器中注册属性
4、使用:继承接口自定义实现
系统初始化器是springboot框架预留的一个扩展点,通过它我们可以在springboot容器刷新之前来向我们的容器中来注册属性
二、实现一个自定义初始化器,直接上代码
自定义初始化器,实现ApplicationContextInitializer
key值是context.initializer.classes,在application.properties中加入context.initializer.classes=com.demo.initializer.DemoInitializer
启动DemoApplication
可以看到,打印出了run demoInitializer,可以写一个DemoController,来测试获取数据
一共有三种实现方式,在这里只是举例其中的一种
三、如何被springboot容器识别并注册进去
通过SpringFactoriesLoader类
1、框架内部使用的通用工厂加载机制
2、从classpath下多个jar包特定的位置读取文件并初始化类
3、文件内容必须是key-value形式,即Properties类型
4、key是全限定名(抽象类、接口)、value是实现,多个实现用,分隔
五、初始化器流程,如何被加载进springboot容器中
先进入getSpringFactoriesInstances(ApplicationContextInitializer.class)方法
1、获得类加载器
2、获得所有的系统初始化器的实现类的全路径名,我们进入SpringFactoriesLoader.loadFactoryNames方法
(1)、查找缓存,如果存在就返回
(2)、通过classLoader去加载资源路径,FACTORIES_RESOURCE_LOCATION = "META-INF/spring.factories",会读取这个文件,会获取所有的jar包中的文件
(3)、如果文件存在,会通过PropertiesLoaderUtils.loadProperties进行读取,然后进行遍历操作,根据key获取值,然后通过StringUtils.commaDelimitedListToStringArray进行分割,然后依次加入到结果中
(4)、依次获取所有jar下的数据后,组装result
(5)、然后通过getOrDefault获取对应的集合
3、调用createSpringFactoriesInstances方法依次创建实例
4、通过AnnotationAwareOrderComparator进行排序
在demo中,有@Order(1)注解,根据大小进行排序
5、通过setInitializers注册到springboot容器中
6、总结流程
六、系统初始化实现是如何被调用的,以及原理
进入run方法,在prepareContext步骤,进入方法,找到applyInitializers(context);方法,此方法就是调用初始化器
在springboot的spring.factories中,可以找到DelegatingApplicationContextInitializer
因为是实现的ApplicationContextInitializer继承自ConfigurableApplicationContext,所以会在run中遍历到
总结流程:
总结实现原理:
1、定义在spring.factories文件中被SpringFactoriesLoader发现注册
2、SpringApplication初始化完毕之后手动添加
3、定义成环境变量被DelegatingApplicationContextInitializer发现注册
以上是关于一起学习springboot源码(系统初始化器)的主要内容,如果未能解决你的问题,请参考以下文章
springboot源码解析-从源码角度分析系统初始化器的实现原理
springBoot学习笔记源码分析之springApplication初始化过程