自定义 spring boot starter 三部曲之三:源码分析 spring.factories 加载过程
欢迎访问我的 GitHub
这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos
本文是《自定义 spring boot starter 三部曲》系列的终篇,前文中我们开发了一个 starter 并做了验证,发现关键点在于 spring.factories 的自动加载能力,让应用只要依赖 starter 的 jar 包即可,今天我们来分析 Spring 和 Spring boot 源码,了解 spring.factories 自动加载原理;
三部曲文章链接
版本情况
本文中涉及到的库的版本:
Spring boot :1.5.9.RELEASE;
JDK :1.8.0_144
初步分析
先回顾 customizeservicestarter 模块中 spring.factories 文件的内容:
从上述内容可以确定今天源码学习目标:
spring 容器如何处理配置类;
spring boot 配置类的加载情况;
spring.factories 中的 EnableAutoConfiguration 配置何时被加载?
spring.factories 中的 EnableAutoConfiguration 配置被加载后做了什么处理;
spring 容器如何处理配置类
ConfigurationClassPostProcessor 类的职责是处理配置类;
ConfigurationClassPostProcessor 是 BeanDefinitionRegistryPostProcessor 接口的实现类,它的 postProcessBeanDefinitionRegistry 方法在容器初始化阶段会被调用(BeanDefinitionRegistryPostProcessor 接口的更多细节请参考《spring4.1.8扩展实战之六:注册bean到spring容器(BeanDefinitionRegistryPostProcessor接口)》);
postProcessBeanDefinitionRegistry 方法又调用 processConfigBeanDefinitions 方法处理具体业务;
processConfigBeanDefinitions 方法中通过 ConfigurationClassParser 类来处理 Configuration 注解,如下图:
如上图红框所示,所有被 Configuration 注解修饰过的类,都会被 parser.parse(candidates)处理,即 ConfigurationClassParser 类的 parse 方法;
parse 方法中调用 processDeferredImportSelectors 方法做处理:找到 Configuration 类中的 Import 注解,对于 Import 注解的值,如果实现了 ImportSelector 接口,就调用其 selectImports 方法,将返回的名称实例化:
小结一下 spring 容器配置类的逻辑:
找出配置类;
找出配置类中的 Import 注解;
Import 注解的值是 class,如果该 class 实现了 ImportSelector 接口,就调用其 selectImports 方法,将返回的名称实例化;
有了上面的结论就可以结合 Spring boot 的源码来分析加载了哪些数据了;
spring boot 配置类的加载情况
我们的应用使用了 SpringBootApplication 注解,看此注解的源码,使用了 EnableAutoConfiguration 注解:
EnableAutoConfiguration 注解中,通过 Import 注解引入了 EnableAutoConfigurationImportSelector.class:
看 EnableAutoConfigurationImportSelector 的源码:
上述源码有三处重点需要关注:
第一,EnableAutoConfigurationImportSelector 是 AutoConfigurationImportSelector 的子类;
第二,EnableAutoConfigurationImportSelector 已经被废弃了,不推荐使用;
第三,文档中已经写明废弃原因:从 1.5 版本开始,其特性由父类 AutoConfigurationImportSelector 实现;
查看 AutoConfigurationImportSelector 的源码,重点关注 selectImports 方法,该方法的返回值表明了哪些类会被实例化:
通过上述代码可以发现,getCandidateConfigurations 方法的调用是个关键,它返回的字符串都是即将被实例化的类名,来看此方法源码:
getCandidateConfigurations 方法中,调用了静态方法 SpringFactoriesLoader.loadFactoryNames,上面提到的 SpringFactoriesLoader.loadFactoryNames 方法是关键,看看官方文档对此静态方法的描述,如下图红框所示,该方法会在 spring.factories 文件中寻找指定接口对应的实现类的全名(包名+实现类):
在 getCandidateConfigurations 方法中,调用 SpringFactoriesLoader.loadFactoryNames 的时候传入的指定类型是 getSpringFactoriesLoaderFactoryClass 方法的返回值:
现在可以梳理一下了:
spring boot 应用启动时使用了 EnableAutoConfiguration 注解;
EnableAutoConfiguration 注解通过 import 注解将 EnableAutoConfigurationImportSelector 类实例化,并且将其 selectImports 方法返回的类名实例化后注册到 spring 容器;
EnableAutoConfigurationImportSelector 的 selectImports 方法返回的类名,来自 spring.factories 文件内的配置信息,这些配置信息的 key 等于 EnableAutoConfiguration;
现在真相大白了:只要我们在 spring.factories 文件内配置了 EnableAutoConfiguration,那么对于的类就会被实例化后注册到 spring 容器;
至此,《自定义 spring boot starter 三部曲》系列就完结了,希望实战加源码分析的三篇文章,能帮助您理解和实现自定义 starter 这种简单快捷的扩展方式;
欢迎关注 InfoQ:程序员欣宸
版权声明: 本文为 InfoQ 作者【程序员欣宸】的原创文章。
原文链接:【http://xie.infoq.cn/article/655ed3947a09806050c57a115】。文章转载请联系作者。
评论