spring源码系列(四)——beanDefinition(2)

Spring源码解析(四)Spring是怎么处理BeanDefinition的? 上一篇文章中分析了 BeanDefinition是怎么被解析出来的,在这一篇文章中我们主要看下 解析完了之后所做的事情; 一、DefaultBeanDefinitionDocumentReader 源码入口 processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) /** ... 阅读详情

在上一篇文章里面我们讨论了一个beanDefintion对象的重要性,为了讨论spring当中的beanDefinition对象我们不得不牵扯出spring当中的bean工厂后置处理器也就是BeanFactoryPostProcessor这个类;继而讨论了BeanFactoryPostProcessor的大概执行时机(BeanFactoryPostProcessor的执行时机很重要而且spring内部做的稍微有点复杂,本文重点来讨论spring内部怎么保证这些执行时机得以严禁的执行,还有如何来扩展spring的bean工厂后置处理器);首先通过一张图简单的理解一下spring容器启动的时候执行调用BeanFactoryPostProcessor后置处理器的大概的方法执行顺序

在这里插入图片描述
上图大概分为④步(这里只是讨论spring如何调用BeanFactoryPostProcessor,在调用之前到底执行了那些方法,上图并不是spring容器启动的所有步骤)
①启动main方法,在main方法里面调用
②AnnotationConfigApplicationContext的无参构造方法,然后②-1在无参构造方法里面首先实例化AnnotatedBeanDefinitionReader对象,实例化这个对象有两个非常重要的意义。 1、这个对象实例化出来有什么用(问题一) ; 2、实例化这个对象的过程中做了哪些事情(问题二)

所有的问题X,文章后面再解释,这里先把步骤搞清楚

继而②-2spring又实例化了一个ClassPathBeanDefinitionScanner对象,这个对象顾名思义就是能够用来完成spring的扫描功能,但是这里提一句——spring内部完成扫描功能并不是用的这个对象,而是在扫描的时候又new了一个新的ClassPathBeanDefinitionScanner对象;换言之这里spring new的对象我们假设他为a,但是spring在真正完成扫描的时候又new了一个b,但是是同一个类都是ClassPathBeanDefinitionScanner,但是为什么需要两个? 3、直接用a不就可以了吗?如果spring内部完成扫描时候没用a,那么a被new出来在哪里使用了?(问题三)到此为止第②步完成;
③调用register(Appconfig.class);首先会把Appconfig类解析成为一个beanDefintion对象(如何把一个类解析称为beanDefinition对象的?这里其实涉及到②-1AnnotatedBeanDefinitionReader对象的意义,如果你明白了②-1这里也就明白了),然后给解析出来的beanDefinition对象设置一些默认属性,继而put到beanDefintionMap当中;为什么需要put到beanDefintionMap呢?在上一篇我们已经解释过这个map就是单纯用来存储beanDefinition的,spring后面会遍历这个map根据map当中的beanDefinition来实例化bean,如果Appconfig类的beanDefintion存在在map当中那么他必然会被spring容器实例化称为一个bean?为什么Appconfig会需要实例化呢?因为Appconfig当中有很多加了@Bean的方法,这些方法需要被调用,故而需要实例化,但是Appconfig类的实例化很复杂比一般类实例化过程复杂很多,涉及到代理涉及到cglib等等,这个我们后面文章解释;这里还需要解释一个问题,为什么Appconfig类是通过register(Appconfig.class);手动put到map当中呢?为什么不是扫描出来的呢?(一般类都是通过扫描出来的),其实也很简单,因为他无法扫描自己,一般类是spring通过解析Appconfig上的@ComponentScan注解然后被扫描到,所以无法扫描自己;接下来便是第
④步,④-1到④-4以后分析,④-5便是我们上篇文章说的执行spring当中的bean工厂后置处理器,也是本文重点讨论的;下图是对上述文字的一个说明——spring容器启动的执行顺序
在这里插入图片描述
接下来解释上面文字里的所有问题
问题一——AnnotatedBeanDefinitionReader这个对象实例化出来有什么用?
先看一下这个类的javadoc,看看作者怎么来解释这个类的
在这里插入图片描述

Convenient adapter for programmatic registration of annotated bean
classes. * This is an alternative to {@link
ClassPathBeanDefinitionScanner}, applying * the same resolution of
annotations but for explicitly registered classes only

按照笔者蹩脚的英文水平我的理解是:这个类作用分为以下两个
1、可用于编程式动态注册一个带注解的bean,什么意思呢?比如我们有一个类A存在com.shadow包下面,并且是一个加注解的类。比如加了@Component,正常情况下这个类A一般是被spring扫描出来的,但是有不正常情况,比如spring并没有扫描到com.shadow包,那么类A就无法被容器实例化。有人可能会问为什么没有扫描到com.shadow包?扫描情况下不会扫描到?其实很简单,假设你的这个类是动态生成,在容器实例化的时候不存在那么肯定不存在,再或者这个包下面有N多类但是只有一个类加了注解,那么其实你不需要去扫描,只需要添加这一个加了注解的类即可,再或者一个类是你和第三方系统交互后得到的。那么这个时候我们可以把这个类通过AnnotatedBeanDefinitionReader的register(Class clazz)方法把一个带注解的类注册给spring(这里的注册其实就是上一篇文章中说的把一个类解析成BeanDefintion对象,然后把这个对象put到beanDefinitionMap当中),写个例子来测试一下他的这个注册bean的功能
在这里插入图片描述
2、可以代替ClassPathBeanDefinitionScanner这个类,具备相同的注解解析功能, ClassPathBeanDefinitionScanner是spring完成扫描的核心类,这个我后面会分析;简而言之,spring完成扫描主要是依靠ClassPathBeanDefinitionScanner这个类的对象,但是AnnotatedBeanDefinitionReader可以替代他完成相同的注解解析,意思就是通过ClassPathBeanDefinitionScanner扫描出来的类A和通过AnnotatedBeanDefinitionReader显示注册的类A在spring内部会一套相同的解析规则;这点上面那个例子已经证明了。

那么AnnotatedBeanDefinitionReader除了动态显示注册一些spring扫描不到的类之外还有什么功能?在初始化spring容器的过程中他主要干了什么事情呢?或者这么说:假设程序中没有需要动态显示注册的类他就没用了吗?再或者AnnotatedBeanDefinitionReader这个类的对象除了注册一些自己的类还有什么应用场景呢?——注册我们的配置类,对于不理解是什么配置的读者可以理解所谓的配置类就是那个加了@Configuration和@ComponentScan的那个类,也就是Appconfig.java;
那么问题来了,为什么配置类需要手动注册呢?很简单因为配置类无法扫描出来,所以需要我们手动注册。为什么无法扫描呢?比如spring完成扫描是需要解析Appconfig.java当中的@ComponentScan注解的值(一般是一个包名),得到这个值之后去扫描这个值所代表的包下面的所有bean;简单的说就是spring如果想要完成扫描必须先提供Appconfig.java,所以Appconfig.java要在一开始就手动注册给spring,spring得到Appconfig.class之后把他解析成BeanDefintion对象,继而去获取@ComponentScan的值然后才开始扫描其他bean;

总结:AnnotatedBeanDefinitionReader的作用1、主要是可以动态、显示的注册一个bean;2、而且具备解析一个类的功能;和扫描解析一个类的功能相同;AnnotatedBeanDefinitionReader的应用场景1、可以显示、动态注册一个程序员提供的bean;2、在初始化spring容器的过程中他完成了对配置类的注册和解析功能;

针对AnnotatedBeanDefinitionReader应用场景的第2点,我在啰嗦几句,一般程序员在初始化spring容器的时候代码有很多种写法,但都是换汤不换药的,我这里举2个栗子。
第一种写法:

AnnotationConfigApplicationContext ac =
				new AnnotationConfigApplicationContext();
				
		//动态注册一个配置类
		ac.register(Appconfig.class);
		
		//调用refresh方法
		//这里很多资料都叫做刷新spring容器
		//但是我觉得不合适,这是硬核翻译,比较生硬
		//笔者觉得理解为初始化spring容器更加精准
		//至于为什么以后慢慢更新再说
		ac.refresh();

第二种写法:

AnnotationConfigApplicationContext ac =
		new AnnotationConfigApplicationContext(Appconfig.class);

这两种写法都初始化spring容器,代码上的区别无非就是第一种写法是调用AnnotationConfigApplicationContext();的无参构造方法,第二种写法是调用了AnnotationConfigApplicationContext(Class<?>... annotatedClasses)有参构造方法;但是你如果翻阅源码第二种写法的内部也是首先调用无参构造方法的,继而内部继续调用register(Appconfig.class)方法,最后调用refresh();方法,和第一种写法的区别是register和refresh是程序员调用的;笔者更推荐第一种写法,因为第一种写法可以在初始化spring容器之前得到AnnotationConfigApplicationContext的对象也就是代码里面的ac对象;用一张图来说明一下这两种写法的异同

在这里插入图片描述

其实第一种方法和第二种方法都可以得到ac对象,那么为什么第一种写法笔者推荐呢?首先第二种方法是在spring容器完成初始化之后的到的ac对象,容器已经初始化了,这个时候得到这个对象能干了事情少了很多;第一种方法在初始化之前得到的,那么能干的事情可多了。①比如我们可以在容器初始化之前动态注册一个自己的bean,就是上文提到的 AnnotatedBeanDefinitionReader的应用场景,②再比如可以利用ac对象来关闭或者开启spring的循环依赖,在笔者的第一篇博客里面也有提到,③还比如程序员可以在容器初始化之前注册自己实例化的BeanDefinition对象。如果你像笔者一样精通spring源码你会发觉提前得到这个ac对象可以做的事情太多了,笔者这里说的三个比如都必须在spring容器初始化之前做才有意义,简而言之就是需要在spring调用refresh方法之间做才有意义;如果你不理解我打个比较污的比方;
假设有机会约到某乔姓网红,无比兴奋之后现在来分析起因和最终结果;起因是她愿意出来和你约会,结果是约会完成最终她还是要回家的。但是过程可以很精彩呀!对比spring的源码起因是你首先成功实例化了一个ac对象(ac成功实例化==你成功约会==new出来的ac对象==约出来的乔姑娘)`,结果是调用ac.refresh()完成初始化spring容器,相当于乔姑娘回家==完成约会;

那么你想一下第一种方式是你成功实例化一个ac对象,在完成初始化之前可以肆意妄为,除了对ac这个对象为所欲为(调用ac的api)之外还可以写任何你自己想写的代码;相当于你成功约到乔姑娘,然后****************你可以拿到她的身份证。但是第二种方式相当于你约到了乔姑娘,但是约会的过程你没办法参与都是姑娘自己安排,她可能和你看完电影之后就告诉你身份证丢了然后各回各家;所以笔者推荐使用第一种方式实例化spring容器。。。。至于原因我已经说的够清楚了。

到此为止已经解释完了问题一——AnnotatedBeanDefinitionReader这个对象实例化出来有什么用?

那么问题二和问题三 下篇文章讨论,为了说清楚spring当中BeanDefintion笔者已经写了两篇博客(根本没有进入BeanDefintion的主题),之前说过会用三篇文章来分析,看来需要食言了,想了一下至少需要五篇才能说清楚

Tartancalib标定OAK-FFC_4p(上) 1.使用Tartancalib标定双目或多目相机前,先对单个相机标定获得内参,再获得外参。 阅读详情

相关推荐

Android HTTPS抓包证书配置全解:Proxyman实战避坑指南

HTTPS抓包本质是中间人(MITM)通信的可信建立过程,其核心在于客户端对代理根证书的信任链配置。在Android平台,自7.0起系统默认不信任用户安装的CA证书,必须通过Network Security Config显式声明trust-anchors,将Proxyman导出的PEM格式根证书纳入App级信任锚点。这一机制区别于iOS和桌面浏览器,导致大量开发者卡在‘证书已安装却无法解密’的误区。技术价值在于打通开发调试闭环:精准定位SSLHandshakeException、绕过证书固定、支持React

weixin_32175665的博客 650

BeanDefinitionStoreException

BeanDefinitionStoreException: Failed to parse configuration class [pro.haichuang.framework.service.zts179.ServiceApplication]; nested exception is org.springframework.context.annotation.ConflictingBeanDefinitionException: Annotation-specified bean name ‘sy

m0_50707445的博客 8481

python模拟银行交易流水

模拟自动生成银行交易流水,其中包括:入账账号、出账账号、交易金额、交易余额、交易时间、出入表示关键字段

qq_31823889的博客 2910

BeanDefinitionStoreException(Bean定义存储异常)可能的原因和解决方法

解决方法:在项目的日志配置中将 Spring 的日志级别设置为 DEBUG 或 TRACE,以获取更详细的日志信息。如果使用了包扫描来自动检测 Bean,确保指定的包路径正确,Spring 能够正确扫描到你的 Bean。解决方法:检查组件扫描的包路径是否正确,并确保所有需要被 Spring 托管的类都在扫描范围内。解决方法:仔细检查 XML 文件,确保语法正确,并且所有的标签和属性都被正确地闭合和命名。解决方法:检查项目中所有的依赖库和框架版本,确保它们与当前使用的 Spring 版本兼容。

Java开源程序猿 6254

西门子S7-1200的PID应用(恒温热水器)

物料清单:1200PLC一台,模拟量输入模块SM1231(PLC自带的输入通道不支持4-20mA电流输入)一个,PT100一个,温度变送器,热得快,固态继电器。 第一步,硬件接线; 第二步,新建1200工程,添加PLC和模拟量输入模块,修改模块的模拟量输入类型为4-20mA,模拟量模块的IO地址为96-103(8个字); 第三步,新建循环组织块OB30,循环时间选择默认点1...

weixin_30835649的博客 6549

YOLO 线性小目标涨点|3890 张输电导线散股 VOC+YOLO 单类别数据集实战,无人机电力缺陷巡检全流程落地

架空输电导线是电网能量传输核心载体,长期受风力摆动、雷击、腐蚀、外力撞击作用,外层铝股极易出现断裂散股故障。导线散股初期仅少量铝丝开裂,肉眼与无人机远距离航拍下属于细长微弱线性小目标;若未及时发现,散股会持续扩张,引发导线过热、断线、大面积停电重大电力安全事故。传统人工巡检存在多重行业痛点:山区、跨江河线路人员无法攀爬登杆,高空作业人身坠落风险极高;无人机单次航拍产出数千张高清图片,人工逐帧筛查微小散股耗时 3-5 天,阴天、逆光、植被遮挡场景漏检率超 45;

lin_xiu的博客 52

解析Spring框架中的XmlBeanDefinitionStoreException异常

通过本文,我们对Spring框架中的XmlBeanDefinitionStoreException异常进行了详细的解析和讨论。我们了解了异常的概述、分析和处理方法,介绍了异常的类层次结构、继承关系和常见属性。我们还给出了实际场景中遇到的异常示例,并提供了常见问题的解决方案和异常处理的最佳实践。在开发过程中,合理处理异常是非常重要的,它有助于提高系统的稳定性和可靠性,减少潜在的错误和故障。因此,我们应该加强对异常的理解和处理,不断优化和改进我们的代码。

博客 2271

阻抗控制器实现机器人关节运动控制

本文先对做个简单的介绍,具体内容后续再更,其他模块可以参考去我其他文章如:PID反馈控制器、前馈控制器、前馈+反馈控制器等等如:机械臂模型(几何解算)控制器、小车底盘运动学模型(几何解算)的控制器、四足机器人模型(预测迭代)的控制器等等如:微分平坦(无人机的轨迹跟随)等等如:MPC优化控制算法如:线性二次调节器(LQR)是基于模型的控制器,使用车辆状态来使误差最小化,Apollo使用LQR进行横向控制。横向控制包含四个组件:横向误差、横向误差的变化率、朝向误差和朝向的变化率。

qq_35635374的博客 364

解决SpringBoot启动时异常:BeanDefinitionStoreException和ConflictingBeanDefinitionException

启动服务出现的异常 org.springframework.beans.factory.BeanDefinitionStoreException: Failed to parse configuration class [cn.StarterImg]; nested exception is org.springframework.context.annotation.ConflictingBea...

数据搬运工 4万+

自动权重化图卷积网络(Auto-Weighted GCN)算法在反洗钱识别中的应用及代码实现

该算法通过自动学习节点之间的权重信息,能够更好地捕捉AML数据中的关系和结构,从而提高反洗钱识别的准确性和效果。传统的AML识别方法通常依赖于专家定义的规则和手动提取的特征,但这些方法在应对大规模和复杂的数据时存在一定的局限性。GCN通过在图上执行卷积操作来捕捉节点之间的关系和结构信息,从而实现对图数据的学习和表示。自动权重化图卷积网络是一种基于GCN的改进算法,能够自动学习节点之间的权重信息,从而更好地捕捉图中的关系。利用自动计算的权重值执行图卷积操作。根据节点之间的相似度,计算每个节点的权重。

syntax_api860的博客 376

SAP VC 可配置物料超级BOM简介

在有些业务中比如:汽车、笔记本、电脑、电梯等产品中,其中组成产品的型号个框架是确认的 ,但是框架内部的BOM是可变的,在客户下销售订单的时候,选取对应的组件 ,让后通过MRP的计算优生产线对这样的销售订单提供生产。这个时候我们需要选择我们需要的内存和硬盘的型号,还记得我们前面创建的特征值对应的吗,A对应的8G、B对应16G、X对应1T硬盘、Y对应2T硬盘,这里我们填写对应的值,我们这里选择16G的内存和2T的硬盘,B和Y。3、当我们选择了可配置物料的生产模式时,基本上就选择了按单生产的生产模式了。

我小时候很黑的博客 1万+

BeanDefinitionStoreException产生原因及解决方案

是 Spring 在加载和解析 Bean 定义时出现问题的标志。常见的原因包括配置文件格式错误、路径问题、占位符解析失败、重复定义 Bean 以及资源不可访问。通过检查配置文件、路径和资源引用,可以有效解决此异常并确保 Spring 应用程序正常启动。

境里婆娑 5546

MoCap 动作捕捉开源库教程

数据通过 tf2 和支持不同 QoS 设置的 /poses 主题直接发布。该软件包最初是为 Crazyswarm 开发的,用于跟踪多达 50 个飞行机器人。

机器人控制与仿真应用 1307

深度解析 Spring 源码:从BeanDefinition源码探索Bean的本质

本文深入解析Spring框架的核心组件之一,即BeanDefinition,探索Bean的本质。首先介绍了BeanDefinition的概念和作用,它是Spring中管理Bean配置元数据的接口,定义了Bean的各种属性和行为。接着,分析了BeanDefinition的实现类以及其重要属性,如Bean的类名、作用域、构造函数、依赖关系等。通过深入研究BeanDefinition的源码,揭示了Spring是如何管理和创建Bean实例的过程。

忆~遂愿的博客 5075

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

spring源码之BeanDefinition

spring源码阅读之BeanDefinition

qq_37729171的博客 1166

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

Spring源码之BeanDefinition的加载

Spring提供了BeanDefinitionRegistry去操作BeanDefinition,BeanDefinitionRegistry接口具有增、删、查(这里的增删查指的是对存放BeanDefinition的集合进行操作)BeanDefinition的能力。通过上面的debug,目前已经知道了Spring怎么注册 配置类以及Processor的BeanDefinition,那么配置类中通过@Bean注解注册的Bean的BeanDefinition是在怎么时候注册的呢?

wsb_2526的博客 1291

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

深入源码:Spring BeanFactoryPostProcessor 定制与修改 BeanDefinition 的原理与实战

BeanFactoryPostProcessor(Bean 工厂后置处理器)是 Spring IoC 容器生命周期中最早暴露给开发者的扩展点之一,它允许容器在**读取完 BeanDefinition 元数据之后、实例化任何普通 Bean 之前**,对 Bean 的定义信息进行读取与修改。本文以 `doocs/source-code-hunter` 仓库中 [Spring-BeanFactoryPo

gitblog_00581的博客 872

spring源码分析之BeanDefinition相关

BeanDeifntion是spring比较核心的组件,它将我们定义的bean都会抽像成对应的BeanDefintion实例对象。了解其相关的知识点对于我们以后通读spring源码以及更加得心应手的应用有很多的好处。本篇博文针对BeanDefintion的家族相关的类与接口进行相关的介绍,同时针对我们项目中相关xml中定义相关的bean(各种各样bean)的属性进行了使用以及应用场景的介绍。以后会追加相关注解(好像没必要相关xml概念可以直接移植到注解的使用方式也是可用的)。

liushangzaibeijing的博客 6万+

Spring源码系列(十六)Spring合并BeanDefinition的原理

1.写在前面 前面的博客,笔者介绍spring中创建Bean的过程,但是还是没有讲完,只讲了如何将这个Bean给实例化出来,但是有关这个bean的所有的内容、属性等等东西,都还没有填充,由于将后面的创建的Bean的流程,需要了解合并BeanDefinition的原理,所以今天笔者打算讲下合并BeanDefinition的原理讲下。 2.什么是合并BeanDefinition 我们先来看个例子,具体的代码如下: package com.ys.mergeBeanDefinition; public class

了不起的盖茨比的博客 2235

spring源码分析系列2:Bean与BeanDefinition关系

Bean与BeanDefinitionBeanDefinition定义动作(操作)其他形态Bean定义操作其他形态 接口表示一种能力,实现了一个接口,即拥有一种能力。 BeanDefinition与Bean的关系, 就好比类与对象的关系. 类在spring的数据结构就是BeanDefinition.根据BeanDefinition得到的对象就是我们需要的Bean. 我认为理解Bean与Bean...

2017年 1966

spring的beanDefinition是什么

在spring源码中,会涉及到bean和beanDefinition这两个概念,接下来,说下什么是bean,什么是beanDefinition

小小少年的博客 3600

Spring扫描BeanDefinition源码

类/接口职责扫描类路径下的组件,生成。处理和,触发扫描流程。读取类元数据(如注解信息),无需加载类。注册到容器。通过以上流程,Spring 完成从组件扫描到注册的全过程。如果需要自定义扫描逻辑(如过滤规则),可以通过扩展TypeFilter或重写方法实现。

weixin_44658106的博客 665

spring源码系列一--BeanDefinition

BeanDefinition是整个Spring实现IOC的核心,也是整个Spring框架的核心,我们在阅读源码之前必须要先搞懂BeanDefinition的含义,以及相应的成员变量,BeanDefinition是一个接口,在Spring中有很多实现类,不同的实现类都有不同的功能。本文会列举我们在阅读源码过程中会遇到的BeanDefinition的实现类以及相应的成员变量的含义。 BeanDefinitionBeanDefiniton与对象的关系BeanDefinition的重要属性与BeanDefiniti

qq_34869357的博客 690

【Spring源码分析】BeanDefinition

Spring源码分析(BeanDefinition)BeanDefinition的加载与注册

scj1022的博客 1332
上一篇: spring源码系列(三)——beanDefinition(1)
下一篇: spring源码系列(五)——番外篇回答网友的问题
子路程序员
博客等级 码龄17年 8814粉丝 10原创
评论 57
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

子路程序员

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值