一直据说spring对java进行了重定义,设计和封装体系比较宏大;加上最近遇到了spring的问题,为了更好地定位问题,最近一段啃了一下spring源码。我用的源码版本是5.2.28,下面就把最近的研究成果作一下分享。java
个人源码阅读目标主要是IOC和AOP这两块,先来看看spring容器加载这块
咱们重点来分析一下前两种容器加载方式。至于嵌入式容器加载方式,后续接触到SpringBoot时再介绍。
虽然如今spring boot大行其道,但就底层的实现来说不少都是基于springframework来实现的。因此咱们由必要分析一下经过xml方式加载容器方式。注解方式容器加载方式做为当前主流一样也是分析的重点(其实它们在执行流程上有不少相同的处理环节)。
先来总体看看这两种方式的容器加载流程spring
注:流程中标记的环节是接下来要陆续分析的重点
从以上两种方式容器加载的流程咱们能够看到,从总体上讲,xml配置解析方式只比注解扫描方式多了一个xml解析的环节,解析的结果最终仍是要封装和注册beandefinition对象。另外注解扫描方式会把三大组件的注册、包的扫描环节提早完成。OK, 接下来咱们一个一个来看。数据结构
容器入口
容器上下文刷新refresh()入口
AbstractRefreshableApplicationContext.refreshBeanFactory()模板方法
AbstractXmlApplicationContext.loadBeanDefinitions()解析配置核心方法
将配置资源封装成InputStream流对象
BeanDefinitionDocumentReader.registerBeanDefinitions()解析和注册beandefinition入口方法
DefaultBeanDefinitionDocumentReader.parseBeanDefinitions()核心解析方法
DefaultBeanDefinitionDocumentReader.parseDefaultElement()默认标签解析过程
解析中间结果包装BeanDefinitionHolder包装对象
BeanDefinitionParserDelegate.parseBeanDefinitionElement()解析bean标签的各类属性和子元素
通用beandefinition数据结构
BeanDefinitionParserDelegate.decorateBeanDefinitionIfRequired()装饰beandefinition其它功能
这种装饰器模式在自定义标签解析有使用
BeanDefinitionReaderUtils.registerBeanDefinition()注册beandefinition工具类方法
BeanDefinition注册的目标接口BeanFactory--->DefaultListableBeanFactory对象
BeanDefinitionParserDelegate.parseCustomElement()解析自定义标签
以上的handlers的解析对于spring来源说有不少,咱们也能够自定义标签对象,之内置的context标签为例,包含如下部分
ComponentScanBeanDefinitionParser.parse()解析<context:component-scan/>标签解析过程
建立ClassPathBeanDefinitionScanner扫描器
ClassPathScanningCandidateComponentProvider.registerDefaultFilters()注册默认的注解类型过滤器
ClassPathBeanDefinitionScanner.doScan()包class文件扫描
ClassPathScanningCandidateComponentProvider.findCandidateComponents()查找符合条件class的过程
ComponentScanBeanDefinitionParser.registerComponents()注册核心三大组件ide
AnnotationConfigApplicationContext构造函数注解扫描入口
AnnotationConfigUtils.registerAnnotationConfigProcessors()注册三大组件,过程同xml解析中组件注册相同
ClassPathBeanDefinitionScanner扫描器注册和NamespaceUri处理器
ClassPathBeanDefinitionScanner.scan()执行包扫描
AbstractApplicationContext.refresh()容器上下文刷新, 同xml配置解析加载相似
注解扫描重写GenericApplicationContext.refreshBeanFactory()方法(没有重要实现);xml配置解析重写的是:AbstractRefreshableApplicationContext.refreshBeanFactory()方法(核心实现就在此);
refresh()容器刷新的后续步骤,两种以上两种容器加载方式都相同,这里就再也不赘述 。函数
最后,让咱们来梳理一下xml配置解析和注解扫描两种方式的beandefinition封装和注解过程
xml配置解析和注册beandefinition调用时序
注解扫描和注册beandefinition调用时序工具
至此两种容器加载方式的beandefinition封装和注册过程就介绍完毕了,有任何关于这块的问题欢迎在下方留言!下次咱们重点解析bean实例化过程。更多spring源码干货请继续关注!ui