微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

spring源码解析 - spring容器加载源码(beandefinition封装和注册过程)

前言

一直听说spring对java进行了重定义,设计和封装体系比较宏大;加上最近遇到了spring的问题,为了更好地定位问题,最近一段啃了一下spring源码。我用的源码版本是5.2.28,下面就把最近的研究成果做一下分享

我的源码阅读目标主要是IOC和AOP这两块,先来看看spring容器加载这块

spring源码解析 - spring容器加载源码(beandefinition封装和注册过程)

我们重点来分析一下前两种容器加载方式。至于嵌入式容器加载方式,后续接触到SpringBoot时再介绍。
虽然现在spring boot大行其道,但就底层的实现来讲很多都是基于springframework来实现的。所以我们由必要分析一下通过xml方式加载容器方式。注解方式容器加载方式作为当前主流同样也是分析的重点(其实它们在执行流程上有很多相同的处理环节)。
先来整体看看这两种方式的容器加载流程

容器加载流程

spring源码解析 - spring容器加载源码(beandefinition封装和注册过程)

spring源码解析 - spring容器加载源码(beandefinition封装和注册过程)

注:流程中标记的环节是接下来要陆续分析的重点
从以上两种方式容器加载的流程我们可以看到,从整体上讲,xml配置解析方式只比注解扫描方式多了一个xml解析的环节,解析的结果最终还是要封装和注册beandeFinition对象。另外注解扫描方式会把三大组件的注册、包的扫描环节提前完成。OK, 接下来我们一个一个来看。

xml配置解析

容器入口

spring源码解析 - spring容器加载源码(beandefinition封装和注册过程)

容器上下文刷新refresh()入口

spring源码解析 - spring容器加载源码(beandefinition封装和注册过程)

AbstractRefreshableApplicationContext.refreshbeanfactory()模板方法

spring源码解析 - spring容器加载源码(beandefinition封装和注册过程)


spring源码解析 - spring容器加载源码(beandefinition封装和注册过程)


AbstractXmlApplicationContext.loadBeanDeFinitions()解析配置核心方法

spring源码解析 - spring容器加载源码(beandefinition封装和注册过程)


spring源码解析 - spring容器加载源码(beandefinition封装和注册过程)


spring源码解析 - spring容器加载源码(beandefinition封装和注册过程)


将配置资源封装成InputStream流对象

spring源码解析 - spring容器加载源码(beandefinition封装和注册过程)


spring源码解析 - spring容器加载源码(beandefinition封装和注册过程)


spring源码解析 - spring容器加载源码(beandefinition封装和注册过程)


spring源码解析 - spring容器加载源码(beandefinition封装和注册过程)


BeanDeFinitionDocumentReader.registerBeanDeFinitions()解析和注册beandeFinition入口方法

spring源码解析 - spring容器加载源码(beandefinition封装和注册过程)


spring源码解析 - spring容器加载源码(beandefinition封装和注册过程)


spring源码解析 - spring容器加载源码(beandefinition封装和注册过程)


spring源码解析 - spring容器加载源码(beandefinition封装和注册过程)


DefaultBeanDeFinitionDocumentReader.parseBeanDeFinitions()核心解析方法

spring源码解析 - spring容器加载源码(beandefinition封装和注册过程)


DefaultBeanDeFinitionDocumentReader.parseDefaultElement()标签解析过程

spring源码解析 - spring容器加载源码(beandefinition封装和注册过程)


解析中间结果包装BeanDeFinitionHolder包装对象

spring源码解析 - spring容器加载源码(beandefinition封装和注册过程)


spring源码解析 - spring容器加载源码(beandefinition封装和注册过程)


BeanDeFinitionParserDelegate.parseBeanDeFinitionElement()解析bean标签的各种属性和子元素

spring源码解析 - spring容器加载源码(beandefinition封装和注册过程)


通用beandeFinition数据结构

spring源码解析 - spring容器加载源码(beandefinition封装和注册过程)


BeanDeFinitionParserDelegate.decorateBeanDeFinitionIfrequired()装饰beandeFinition其它功能

spring源码解析 - spring容器加载源码(beandefinition封装和注册过程)


spring源码解析 - spring容器加载源码(beandefinition封装和注册过程)


这种装饰器模式在自定义标签解析有使用
BeanDeFinitionReaderUtils.registerBeanDeFinition()注册beandeFinition工具类方法

spring源码解析 - spring容器加载源码(beandefinition封装和注册过程)


BeanDeFinition注册的目标接口beanfactory--->DefaultListablebeanfactory对象

spring源码解析 - spring容器加载源码(beandefinition封装和注册过程)


BeanDeFinitionParserDelegate.parseCustomElement()解析自定义标签

spring源码解析 - spring容器加载源码(beandefinition封装和注册过程)


spring源码解析 - spring容器加载源码(beandefinition封装和注册过程)


以上的handlers的解析对于spring来源说有很多,我们也可以自定义标签对象,以内置的context标签为例,包含以下部分

spring源码解析 - spring容器加载源码(beandefinition封装和注册过程)


spring源码解析 - spring容器加载源码(beandefinition封装和注册过程)


spring源码解析 - spring容器加载源码(beandefinition封装和注册过程)


ComponentScanBeanDeFinitionParser.parse()解析<context:component-scan/>标签解析过程

spring源码解析 - spring容器加载源码(beandefinition封装和注册过程)


创建ClasspathBeanDeFinitionScanner扫描器

spring源码解析 - spring容器加载源码(beandefinition封装和注册过程)


spring源码解析 - spring容器加载源码(beandefinition封装和注册过程)


ClasspathScanningCandidateComponentProvider.registerDefaultFilters()注册认的注解类型过滤器

spring源码解析 - spring容器加载源码(beandefinition封装和注册过程)


ClasspathBeanDeFinitionScanner.doScan()包class文件扫描

spring源码解析 - spring容器加载源码(beandefinition封装和注册过程)


ClasspathScanningCandidateComponentProvider.findCandidateComponents()查找符合条件class的过程

spring源码解析 - spring容器加载源码(beandefinition封装和注册过程)


spring源码解析 - spring容器加载源码(beandefinition封装和注册过程)


spring源码解析 - spring容器加载源码(beandefinition封装和注册过程)


spring源码解析 - spring容器加载源码(beandefinition封装和注册过程)


ComponentScanBeanDeFinitionParser.registerComponents()注册核心三大组件

spring源码解析 - spring容器加载源码(beandefinition封装和注册过程)


spring源码解析 - spring容器加载源码(beandefinition封装和注册过程)

注解扫描

AnnotationConfigApplicationContext构造函数注解扫描入口

spring源码解析 - spring容器加载源码(beandefinition封装和注册过程)


spring源码解析 - spring容器加载源码(beandefinition封装和注册过程)


AnnotationConfigUtils.registerannotationConfigProcessors()注册三大组件,过程同xml解析中组件注册相同

spring源码解析 - spring容器加载源码(beandefinition封装和注册过程)


ClasspathBeanDeFinitionScanner扫描器注册和NamespaceUri处理器

spring源码解析 - spring容器加载源码(beandefinition封装和注册过程)


ClasspathBeanDeFinitionScanner.scan()执行包扫描

spring源码解析 - spring容器加载源码(beandefinition封装和注册过程)


AbstractApplicationContext.refresh()容器上下文刷新, 同xml配置解析加载类似

spring源码解析 - spring容器加载源码(beandefinition封装和注册过程)


spring源码解析 - spring容器加载源码(beandefinition封装和注册过程)


spring源码解析 - spring容器加载源码(beandefinition封装和注册过程)


注解扫描重写GenericApplicationContext.refreshbeanfactory()方法(没有重要实现);xml配置解析重写的是:AbstractRefreshableApplicationContext.refreshbeanfactory()方法(核心实现就在此);
refresh()容器刷新的后续步骤,两种以上两种容器加载方式都相同,这里就不再赘述 。

调用时序

最后,让我们来梳理一下xml配置解析和注解扫描两种方式的beandeFinition封装和注解过程
xml配置解析和注册beandeFinition调用时序

spring源码解析 - spring容器加载源码(beandefinition封装和注册过程)


注解扫描和注册beandeFinition调用时序

spring源码解析 - spring容器加载源码(beandefinition封装和注册过程)

总结

至此两种容器加载方式的beandeFinition封装和注册过程就介绍完毕了,有任何关于这块的问题欢迎在下方留言!下次我们重点解析bean实例化过程。更多spring源码干货请继续关注!

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。