spring源码学习笔记1——解析xml生成BeanDefinition的过程解析

news/2024/5/19 21:35:43/文章来源:https://www.cnblogs.com/cuzzz/p/16607924.html

spring源码学习笔记1——解析xml生成BeanDefinition的过程解析

一丶Spring解析Xml生成BeanDefinition的流程

1.指定xml路径

解析xml首先需要知道xml的位置,如下我们构造了ApplicationContext

ApplicationContext context =new ClassPathXmlApplicationContext("bean.xml");

首先根据setConfigLocations方法设置配置文件位置,从这里我们知道Spring支持多个配置文件一起加载

2.构建BeanFactory

生成的BeanDefinition需要放到BeanFactory中,所有在解析之前先生成BeanFactory

这里注释表示会通知子类刷新BeanFactory,这个子类是指AbstractApplicationContext的子类,这里子类是指AbstractRefreshableApplicationContext(ClassPathXmlApplicationContext的父类,但是refreshBeanFactory在父类中进行了实现)

3.解析xml生成BeanDefinition

这里引入一个新的概念,BeanDefinitionReader,这是Spring对BeanDefinition读取提供的规范接口,Spring支持基于注解和基于配置生成BeanDefinitiond的不同方式,所有抽取出BeanDefinitionReader,BeanDefinitionReader负责根据资源生成BeanDefinition并且注解到BeanDefinitionRegistry

解析Document生成BeanDefinition并且注册的操作委托给BeanDefinitionDocumentReader的实现类DefaultBeanDefinitionDocumentReader进行

1.判断当前xml的profile是否需要加载

如果是默认的Namespace(指xmlns=http://www.springframework.org/schema/beans)读取profile (多个环境生效的xml 可以使用 【,;】进行分割,还可以使用【!】表示不在哪个环境下生效,比如!dev表示dev环境下这个xml中的bean将不被注入)

这里会先拿配置文件中的spring.profiles.active,如果不支持那么不处理这个xml,如果spring.profiles.active对于的值是空,那么拿spring.profiles.default中指定的配置,如果也不支持当前环境 那么不处理当前xml

2.解析xml生成BeanDefinition

接下来我们看下是怎么解析每一个<bean></bean>生成BeanDefinition的

  • 解析Import标签

对于这种内容,会针对resource的内容解析成Resouce再此调用解析成xml生成Bean的方法——loadBeanDefinitions,存在一点点逻辑就是可以当前绝对路径,url,相对路径去解析resouce中内容

  • 解析alias标签

    为Bean配置别名

    根本上都是向BeanFactory注册,数据维护在aliasMap属性中,这里存在逻辑,如果name和alias相同会进行删除(因为name是bean标签指定的bean名称,别名也是这个的话那么没有必要注册(直接可以通过bean名称拿到bean)),还会检查是否存在别名的循环引用,对于name=a alias=b 和name=b,alias=a 这种情况会抛出异常

  • 解析Bean标签

    见剩余章节

  • 解析Beans标签

    循环处理里面每一个Bean标签内容

二丶解析<Bean>生成BeanDefinition

1,BeanDefinitionParserDelegate解析Bean标签生成BeanDefinitionHolder

BeanDefinitionHolder是BeanDefinition的包装器,里面持有BeanDefinition和Bean的别名,Bean名称,并且记录元数据的来源

1.1获取BeanName 和Bean别名

id是bean的唯一表示,name可以使用,;分割来表示别名,如果没有指定id,那么beanName默认使用name属性中的第一个=>a,;b,;cbeanName是a,还会检查BeanName是否重复

  1. 解析其他属性生成BeanDefinition

    1. 首先会拿class 和 parent指定的内容

      !

      Parent标签允许子类对一些属性不进行值的指定,而是直接使用父类中指定的值
      相当于parent 可以起到模板的作用
      

1.2解析scope,abstract,lazy-init,autowire等标签

  1. abstract的作用:

    ApplicationContext会预实例化所有singleton的bean。因此很重要的一点是:如果你只想把一个(父)bean定义当作模板使用,而它又指定了class属性,那么你就得将'abstract'属性设置为'true'

  2. autowire的作用

    这里并不是立即进行依赖注入,只是对autowire的值进行解析,后续创建对象的时候才会依据值的不同有不同的行为

  3. scope的作用

    1. Singleton :一个Spring 容器中只有一个Bean 的实例,此为Spring 的默认配置,全容器共享一个实例。
    2. Prototype :每次调用新建一个Bean 的实例。
    3. Request: Web 项目中,给每一个http request 新建一个Bean 实例。
    4. Session: Web 项目中,给每一个http session 新建一个Bean 实例。
    5. Global Session :这个只在portal 应用中有用,给每一个global http session 新建一个Bean实例。
  4. lazy-init

    lazy-init属性用于配置当前的springbean是否延迟加载。所谓延迟加载就是创建spring容器的时候是不创建对象的,当第一次获取该对象时才会实例化该对象

    如下可以指定整个xml 是否延迟加载

    !

  5. depends-on

depends-on表现情况就是:如果A 的depends-on配置的是B,则spring会在创建A之前先创建B,会在销毁B之前先下回A。

  1. autowire-candidate

autowire-candidate:设置当前bean在被其他对象作为自动注入对象的时候,是否作为候选bean,默认值是true

  1. primary

    spring为我们注入bean的时候,如果存在类型相同的多个bean,如接口Service存在实现类A和B,但是A指定了Primary=true 那么会优先注入A

  2. init-method

    初始化方法,会在实例化bean之后被回调

  3. destroy-method

    销毁方法,Bean被销毁的时候被回调使用

  4. factory-method

    factory-method表示使用当前描述的方法指定创建bean的方法,factory-bean用于指定自己定义的类,factory-method用于指定创建bean的方法,另外创建对象的方法可以是静态的也可以是实例的。

1.4 meta 标签

meta 所声明的 key 并不会在 Bean 中体现,只是一个额外的声明,当我们需要使用里面的信息时,通过 BeanDefinition 的 getAttribute() 获取。

1.5 lookup-method 标签

lookup-method 可以将定义bean的方法替换成另外一个bean中的方法

Spring框架通过使用CGLIB库中的字节码生成来动态生成重写该方法的子类,从而实现这种方法注入

<bean id="期望注入的bean A" class="A的class"><lookup-method name="A的某一个方法" bean="替换成Bbean中的方法"/>
</bean>

1.6 replaced-method 标签

和lookup-method 差不多但是要求替换目标bean实现 MethodReplacer 接口

<bean id="myValueCalculator" class="x.y.z.MyValueCalculator">把myValueCalculator 中的 computeValue 方法使用 replacementComputeValue 替换<replaced-method name="computeValue" replacer="replacementComputeValue"><arg-type>String</arg-type></replaced-method>
</bean>
<bean id="replacementComputeValue" class="a.b.c.ReplacementComputeValue"/>

1.7 constructor-arg 标签

通过构造函数注入。可以通过指定入参的名称,入参的index,入参的值(ref or value)来注入,还可以指定入参的类型(type属性)

1.8 property 标签

通过对应的setter方法注入,通过设置name属性 指定 字段的setter方法,使用ref 或者value 来标签字段需要注入成什么内容

1.9 qualifier 标签

qualifier 标签,和@Qualifier 差不多,qualifier标签是用来定义需要注入bean的别名的,代表这个bean必须根据名称(ByName)才会被选为候选bean(一般是ByType),即根据bean的名称进行注入.

2.注册BeanDefinition

解析完xml 之后,得到BeanDefinitionHolder,后续使用BeanDefinitionReaderUtils将BeanDefinition注册到BeanRegistry,在 DefaultListableBeanFactory 底层是使用ConcurrentHashMap 来维护bean名称和BeanDefinition的关系,别名也是使用ConcurrentHashMap 来维护Bean名称

2.1 注册BeanDefinition

DefaultListableBeanFactory 为例子
2.1.1 检验是否合法

如果是AbstractBeanDefinition 对象,那么调用validate方法

不能同时指定方法重写 且 指定bean有工厂方法产生,如果指定了重写但是类中没有这个方法 也抛出异常

2.1.2 存在相同bean名称时

如果不允许覆盖BeanDefinition,那么抛出异常,否则覆盖

2.1.3 注册

维护bean 名称和 BeanDefinition的map,把Bean名称加入到beanDefinitionNames 集合中

2.2 注册 别名

使用ConcurrentHashMap 维护别名和bean的名称,会检查是否存在别名循环的情况,比如A的别名是B,B的别名是A这种情况抛出异常

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_379858.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

IOC

介绍 什么是SpringIOC,就是把每一个bean(实体类)与bean(实体类)之间的关系交给第三方容器进行管理。关键类BeanFactory IOC的顶层容器,描述了IOC的规范。 BeanFactory是一个接口,是Spring中工厂的顶层规范,IOC的核心接口。 定义了getBean()、containsBean()等管理Bean的通用…

JUC进阶

JUC进阶 wait和sleep的区别sleep是Thread的静态方法,wait是Object方法sleep不会释放锁,它也不需要占用锁,wait会释放锁但调用它的前提是当前线程占有锁wait必须在同步代码块中Lock锁public class LockTest { public static void main(String[] args) { Ticket t…

Spring 03: 基于xml的构造方法注入

构造方法注入具体有3种注入方式:通过构造方法的 a.参数名称注入 b.参数下标注入 c.默认参数顺序注入参数名称注入School实体类package com.example.pojo03;public class School {private String name;private String address;@Overridepublic String toString() {return &…

Vmware 安装CentOS 7

Vmware 安装CentOS 7 创建虚拟机 1、新建虚拟机,选择自定义(高级),下一步。其他默认下一步。选择操作系统Linux,CentOS 7 64位,下一步。输入主机名称,虚拟机存储位置。 2、输入内核数量3、输入内存大小,下一步,其他默认下一步。4、指定磁盘大小,下一步5、自定义硬件,…

深度学习基础课:课程介绍

大家好~我开设了“深度学习基础班”的线上课程,带领同学从0开始学习全连接和卷积神经网络,进行数学推导,并且实现可以运行的Demo程序 本文为第一节课:课程介绍的复盘文章深度学习基础课:课程介绍 大家好~我开设了“深度学习基础班”的线上课程,带领同学从0开始学习全连接…

一台服务器​最大并发 TCP 连接数多少

一台服务器​最大并发 TCP 连接数多少 入门小站 入门小站 2022-07-06 22:10 发表于湖北收录于合集#Linux485个 #tcp4个首先,问题中描述的65535个连接指的是客户端连接数的限制。在tcp应用中,server事先在某个固定端口监听,client主动发起连接,经过三路握手后建立tcp连接。那…

js的原型

prototype 概述:所有的函数都拥有一个属性 这个属性称为prototype 他是一个对象空间(里面就可以存放对应的数据)他被称为显式原型从上述代码 大家可以看到对应的构造函数的prototype和对应的实例对象的 __proto__ 是相等,那么也就证明了对应俩个内容其实是一个对象。那么我…

Condition介绍

Condition Condition是一种多线程通信工具,表示多线程下参与数据竞争的线程的一种状态,主要负责多线程环境下对线程的挂起和唤醒工作。 方法 // ========== 阻塞 ========== // 造成当前线程在接到信号或被中断之前一直处于等待状态。 void await() throws InterruptedExcept…

解决goland在mac m1下无法调试问题

背景 新电脑mac m1 goland调试抛出异常 异常信息 第一次异常信息 could not launch process: can not run under Rosetta, check that the installed build of Go is right for your CPU architecture 原因是goland版本安装错了. 下载地址:https://www.jetbrains.com/zh-cn/go…

排序(上)

目录冒泡排序(Bubble Sort)插入排序(Insertion Sort)选择排序(Selection Sort)冒泡排序和插入排序的比较 最经典的、最常用的有:冒泡排序、插入排序、选择排序、归并排序、快速排序、计数排序、基数排序、桶排序 冒泡排序(Bubble Sort) 冒泡排序只会操作相邻的两个数据…

Codeforces Round #815 (Div. 2) 题解

Codeforces Round #815 (Div. 2) 全场题解CF1720A. Burenka Plays with Fractions给出两个分数 $ \dfrac{a}{b}$ 和 \(\dfrac{c}{d}\) ,你每次操作能够选择其中一个分数的分子或分母,将其乘上任意一个整数(当然不能对分母乘 \(0\))。要求求出能够使两个分数相等的最小操作次…

2022 牛客多校 Extra 第九场部分题解

2022 牛客多校第九场 & Extra 部分题解 前段时间沉迷生活大爆炸 & 原神 & vtb & galgame & 番无法自拔,因此咕到现在。。。 Cmostp 挺妙的题。本以为有一只 log 的做法。 覆盖后的颜色变换不多,可以用 set+树剖或者阉割版的lct+树状数组,我写了后者,把…

【小迪安全】04:基础入门-web源码扩展

(XYCMS搬家公司建站系统) 查找数据库文件路径: 发现后缀名为mdb文件——为asp网站特有的 打开mdb文件找到 admin_user数据库可以找到用户名和密码

解决无法访问GitHub

一、获取IP地址可以直接通过网站 查询域名 github.com 的IP地址,无论哪种方法一定得是通过自己本机查到的IP,网上别人查到的IP你不一定有用。https://www.ipaddress.com/二、修改hosts文件 Windows hosts文件路径: C:\Windows\System32\drivers\etc 在对应目录找到hosts文件,…

Intellij IDEA 快速生成注释模板教程

生成类注释 File–>settings–>Editor–>File and Code Templates–>Class (1)@BelongsProject:当前项目的名称 (2)@BelongsPackage:当前包的名称 (3)@Author:作者姓名(可以写死,写成你的名字) (4)@CreateTime:该类创建的时间 (5)@Description:对…

第一章 计算机硬件基础

1、数据的表示R进制的表示(R可为二、八、十、十六) 原则:逢R进一 Decimail 十进制;Binary 二进制; Octal 八进制;Hex 十六进制R进制转十进制(按权展开) 以二进制1101为例:十进制转二进制(短除法)二进制与八、十六进制之间的转换问题:为啥八进制数对应三位二进制数,…

java初步学习(基于黑马的课进行自学,初学者,不喜勿喷)6

初步学习 流程控制语句 顺序结构 顺序结构指java运行结果的排序由代码的先后顺序决定 例if语句 if的基本格式为 if (关系表达式){ 语句体; } 如果满足“()”内的关系表达式,则运行“{}”内的语句体,反之则不会运行 以该模型为例 需求:键盘录入一整数来表示身体状况,若该值大…

第二章 数据通信基础

一、数据通信系统 通信术语:信息 数据 信号 分为模拟信号:连续和数字信号:离散 码元:单位时间内的一段数字脉冲,单位Band----------码元速率也叫波特速率,B=1/T(HZ)二、数据通信系统模型传输介质传输介质-光纤对比多模光纤(小 贵 好 远 快 ),单模光纤的芯径要小…

15.DC导出CA让Horizon Client CA导入

客户端安装后提示证书错误 去同域服务器任意一台的mmc-添加证书中找到 右键-所有任务-导出导出过程放到桌面复制去其他客户端mmc中导入导入后的证书 导入后能登录并且为绿色

前后端分离Web项目 - 环境部署流程

准备环境购买一个云服务器(我用的是Amazon的Ubuntu),并记录/查询当前用户ubuntu的公网IP。登录服务器后查询Ubuntu公网IP::curl ifconfig.me (如果没有 curl ,先安装一下: sudo apt-get install curl )PS:服务器需要提前安装好前后端需要的包,比如相关sdk,runtime,…