热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

【Spring6源码・IOC】BeanDefinition的加载

哎呀,又是午夜时分,又是一个失眠的夜晚,和去年一样,记得去年今日,也是睡不着觉,就注册了csdn


哎呀,又是午夜时分,又是一个失眠的夜晚,和去年一样,记得去年今日,也是睡不着觉,就注册了csdn的账号,开始写东西,csdn真是深夜最好的安魂剂。

Spring都发布了6.0,这不赶紧看看源码,咱们来一起学习学习,废话不多说了,开始吧。



文章目录


  • IOC核心流程简介
  • BeanDefinition的设计思想
  • 解析@ComponentScan
  • 解析@Bean
  • 解析@Import



IOC核心流程简介

环境:Spring6、SpringBoot3.0、JDK17



读源码小tips:


  1. 多看注释
  2. 梳理整体设计思想
  3. don’t care

IOC是一个容器,对象的创建、使用和销毁都是由IOC容器来管理。

小白可以先看这篇:《五分钟带你速通Spring IOC》



大体的流程如下:


  1. 加载配置文件(XML\YAML…)、配置类,并解析成BeanDefinition
  2. BeanFactoryPostProcessor对BeanDefinition做一些处理
  3. 实例化bean对象
  4. 初始化bean对象(属性填充等),并且在初始化前后通过BeanPostProcessor对bean对象进行相关处理


所以,我们先从第一步开始:BeanDefinition的封装


BeanDefinition的设计思想

BeanDefinition是存储Bean的元信息,包括Bean本身的信息,以及Bean注解信息。这个信息就是从我们的配置文件以及配置类等加载以及进行一系列处理而来。



以注解这种方式来说,大概有三种:


  1. 以@ComponentScan扫描的方式,包括@Controller、@Service、@Repository、@Component。
  2. 以@Configuration声明的配置类,内部会用@Bean来声明需要创建的对象
  3. @Import,用来引入其他组件

首先会构建一个解析器去扫描所有的@Controller、@Service、@Repository、@Component、@Configuration类

通过这三种方法加载 BeanDefinition,并将他们放到缓存beanDefinitionMap中。

那么是如何解析这些注解的?时机是什么?我们来一起看一看



相关资料:《@Import注解的作用以及如何使用》



解析@ComponentScan

以SpringBoot的启动来说,我们通过SpringApplication#run,最终调用AbstractApplicationContext 的 refresh() 方法。

在这里插入图片描述
invokeBeanFactoryPostProcessors这个方法就是用来加载BeanDefinition。



通过如下方法


  1. PostProcessorRegistrationDelegate#invokeBeanFactoryPostProcessors
  2. ConfigurationClassPostProcessor#postProcessBeanDefinitionRegistry
  3. ConfigurationClassPostProcessor#processConfigBeanDefinitions

最后进入到ConfigurationClassPostProcessor 的 processConfigBeanDefinitions 方法
在这里插入图片描述
这里是找到我们启动类的BeanDefinition,然后构建了一个ConfigurationClassParser解析器,去扫描我们加上注解的类,并加载为 BeanDefinition。

在这里插入图片描述

进入 parse 方法,最终我们会来到,老套路了,方法前面加do的,都是比较核心的方法,包括后面扫描的时候有一个doScan。
在这里插入图片描述
进入到 ConfigurationClassParser 的 doProcessConfigurationClass 方法
在这里插入图片描述
这里可以看到,这个又有一个解析器ComponentScanAnnotationParser,它是用来处理@Controller、@Service、@Repository、@Component、@Configuration这些注解的。

我们来看看它做了什么事。

在这里插入图片描述

首先构建了一个ClassPathBeanDefinitionScanner对象,然后对它进行一些set操作,最后进入核心方法doScan中。

在这里插入图片描述
首先findCandidateComponents(basePackage) 方法会扫描启动类所在的包(默认),找到符合条件的类(被@ComponentScan扫描到的,以及@Configuration),最后在通过registerBeanDefinition(definitionHolder, this.registry)方法将BeanDefinition注册金beanDefinitionMap中。

我们可以细讲一下这两个地方,首先看如何筛选类的。

findCandidateComponents(basePackage) 方法最后进入下面这个核心方法

在这里插入图片描述
首先通过getResourcePatternResolver().getResources(packageSearchPath)加载出所有的类并封装成Resource数组,然后在通过isCandidateComponent(metadataReader)筛选出符合的类,最后构建成BeanDefinition类,添加到set集合中,最后返回。

registerBeanDefinition(definitionHolder, this.registry)方法呢,就比较直接了,如果在缓存中获取不到就直接加锁,然后添进缓存中。
在这里插入图片描述
到此,@ComponentScan 就扫描完成了,BeanDefinition 也加载完成了。


解析@Bean

大多时候,@Bean是和@Configuration一起使用的,由上文可知,@Configuration相关类在ComponentScanAnnotationParser处就会被解析到。

如图上面这个方法是上文一直在讲解的(讲@ComponentScan扫描到的类加入缓存中),下面这个就是真正解析@Bean和@Import并将其加入缓存的方法。

在这里插入图片描述

我们来看看吧,因为一个配置类可能不止一个@Bean,所以循环对每一个@Bean处理

在这里插入图片描述
最后通过this.registry.registerBeanDefinition(beanName, beanDefToRegister)将@Bean相关BeanDefinition添加进beanDefinitionMap中。


解析@Import

其实@Import更为简单一些,这里优先判断其是否为@Import。
在这里插入图片描述
在parser.parse 方法中,先将 类转化为一个 ConfigurationClass 类,设置到它的 importedBy 属性中。然后在之后的 loadBeanDefinitions 方法中,判断 ConfigurationClass 的 importedBy 属性是否为空,如果不为空,说明是需要加载的,将它加载为 BeanDefinition,最后registerBeanDefinitionForImportedConfigurationClass(ConfigurationClass configClass)方法中的this.registry.registerBeanDefinition(definitionHolder.getBeanName(), definitionHolder.getBeanDefinition())将BeanDefinition添加进IOC容器中。

在这里插入图片描述

完事了。等下一章吧







推荐阅读
  • 本文介绍了Web学习历程记录中关于Tomcat的基本概念和配置。首先解释了Web静态Web资源和动态Web资源的概念,以及C/S架构和B/S架构的区别。然后介绍了常见的Web服务器,包括Weblogic、WebSphere和Tomcat。接着详细讲解了Tomcat的虚拟主机、web应用和虚拟路径映射的概念和配置过程。最后简要介绍了http协议的作用。本文内容详实,适合初学者了解Tomcat的基础知识。 ... [详细]
  • 本文讨论了在Spring 3.1中,数据源未能自动连接到@Configuration类的错误原因,并提供了解决方法。作者发现了错误的原因,并在代码中手动定义了PersistenceAnnotationBeanPostProcessor。作者删除了该定义后,问题得到解决。此外,作者还指出了默认的PersistenceAnnotationBeanPostProcessor的注册方式,并提供了自定义该bean定义的方法。 ... [详细]
  • Spring常用注解(绝对经典),全靠这份Java知识点PDF大全
    本文介绍了Spring常用注解和注入bean的注解,包括@Bean、@Autowired、@Inject等,同时提供了一个Java知识点PDF大全的资源链接。其中详细介绍了ColorFactoryBean的使用,以及@Autowired和@Inject的区别和用法。此外,还提到了@Required属性的配置和使用。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • Spring源码解密之默认标签的解析方式分析
    本文分析了Spring源码解密中默认标签的解析方式。通过对命名空间的判断,区分默认命名空间和自定义命名空间,并采用不同的解析方式。其中,bean标签的解析最为复杂和重要。 ... [详细]
  • Linux重启网络命令实例及关机和重启示例教程
    本文介绍了Linux系统中重启网络命令的实例,以及使用不同方式关机和重启系统的示例教程。包括使用图形界面和控制台访问系统的方法,以及使用shutdown命令进行系统关机和重启的句法和用法。 ... [详细]
  • 本文介绍了如何使用php限制数据库插入的条数并显示每次插入数据库之间的数据数目,以及避免重复提交的方法。同时还介绍了如何限制某一个数据库用户的并发连接数,以及设置数据库的连接数和连接超时时间的方法。最后提供了一些关于浏览器在线用户数和数据库连接数量比例的参考值。 ... [详细]
  • t-io 2.0.0发布-法网天眼第一版的回顾和更新说明
    本文回顾了t-io 1.x版本的工程结构和性能数据,并介绍了t-io在码云上的成绩和用户反馈。同时,还提到了@openSeLi同学发布的t-io 30W长连接并发压力测试报告。最后,详细介绍了t-io 2.0.0版本的更新内容,包括更简洁的使用方式和内置的httpsession功能。 ... [详细]
  • 在重复造轮子的情况下用ProxyServlet反向代理来减少工作量
    像不少公司内部不同团队都会自己研发自己工具产品,当各个产品逐渐成熟,到达了一定的发展瓶颈,同时每个产品都有着自己的入口,用户 ... [详细]
  • 本文介绍了如何使用C#制作Java+Mysql+Tomcat环境安装程序,实现一键式安装。通过将JDK、Mysql、Tomcat三者制作成一个安装包,解决了客户在安装软件时的复杂配置和繁琐问题,便于管理软件版本和系统集成。具体步骤包括配置JDK环境变量和安装Mysql服务,其中使用了MySQL Server 5.5社区版和my.ini文件。安装方法为通过命令行将目录转到mysql的bin目录下,执行mysqld --install MySQL5命令。 ... [详细]
  • 本文讲述了如何通过代码在Android中更改Recycler视图项的背景颜色。通过在onBindViewHolder方法中设置条件判断,可以实现根据条件改变背景颜色的效果。同时,还介绍了如何修改底部边框颜色以及提供了RecyclerView Fragment layout.xml和项目布局文件的示例代码。 ... [详细]
  • http:my.oschina.netleejun2005blog136820刚看到群里又有同学在说HTTP协议下的Get请求参数长度是有大小限制的,最大不能超过XX ... [详细]
  • springmvc学习笔记(十):控制器业务方法中通过注解实现封装Javabean接收表单提交的数据
    本文介绍了在springmvc学习笔记系列的第十篇中,控制器的业务方法中如何通过注解实现封装Javabean来接收表单提交的数据。同时还讨论了当有多个注册表单且字段完全相同时,如何将其交给同一个控制器处理。 ... [详细]
  • 本文介绍了南邮ctf-web的writeup,包括签到题和md5 collision。在CTF比赛和渗透测试中,可以通过查看源代码、代码注释、页面隐藏元素、超链接和HTTP响应头部来寻找flag或提示信息。利用PHP弱类型,可以发现md5('QNKCDZO')='0e830400451993494058024219903391'和md5('240610708')='0e462097431906509019562988736854'。 ... [详细]
  • r2dbc配置多数据源
    R2dbc配置多数据源问题根据官网配置r2dbc连接mysql多数据源所遇到的问题pom配置可以参考官网,不过我这样配置会报错我并没有这样配置将以下内容添加到pom.xml文件d ... [详细]
author-avatar
wrennlatsha_188
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有