谈谈Spring的常见基础概念

文章是对Spring一些基础的底层概念进行分析,后续再遇到这些问题的时候,可以采用这些步骤进行详细解释。

一.谈谈SpringIOC的理解,原理与实现?

总:

1.控制反转

(1)原来的对象是由使用者来进行控制,有了Spring之后,可以把整个对象交给Spring来帮我们进行管理

(2)它有一个依赖注入(DI)的概念:把对应的属性的值注入到具体对象中,可以通过@Autowired、@PopulateBean也可以完成属性值的注入。

2.容器

(1)存储对象,使用Map结构进行存储,在Spring中一般存在三级缓存SingletonObject存放完整的Bean对象,使用对象的时候通过SingletonObject获取;

(2)整个bean的生命周期从创建到使用到销毁的全部过程都是由容器来管理。

分:

1.一般谈IOC容器的时候要涉及到容器的创建过程(BeanFactory、DefaultListableBeanFactory),容器它有一个最上层的根接口,叫做BeanFactory,它里面只是一个接口,没有提供对应的子类实现,我们在实际调用过程中,最最用普遍的就是一个DefaultListableBeanFactory,包括我们使用的时候也会优先创建当前的Bean工厂,创建Bean工程后会优先向Bean工厂中设置一些参数(BeanPostProcessor、Aware接口的子类)等等属性

2.加载解析Bean对象,准备要创建的Bean对象的定义对象BeanDefinition(xml或者注解的解析过程),因为只有解析后才能获取到完整的Bean对象,最终结果是获取到BeanDefinition对象;

3.BeanFactoryPostProcessor的处理,此处是扩展点(为什么Spring有一个完整的生态,发展的这么好,就是因为它提供了很多默认的扩展点,来帮助我们进行了很多点的扩充知识),用的比较多的两个扩展点是PlaceHolderConfigurSupport、ConfigurationClassPostProcessor

4.BeanPostProcessor的注册功能,方便后续对Bean对象完成具体的扩张功能

(前四步完成后,代表BeanFactory准备的差不多了)

5.通过反射的方式将BeanDefinition对象实例化成具体的Bean对象

6.Bean对象的初始化过程(填充数据、调用Aware子类的方法、调用BeanPostProcessor前置处理方法,调用init-method方法、调用BeanPostProcessor后置处理方法);

7.生产完整的Bean对象,通过getBean方法可以直接获取

8.销毁过程

以上就是对IOC的整体理解,包含了一些详细处理过程,具体详细的逻辑需要看源码分析,但是总结一下,就是Spring中的Bean都是通过反射的方式生成的,同时其中包含了很多的扩展点,比如最常见的对BeanFactory的扩展、对Bean的扩展,除此之外,IOC中最核心的也就是填充具体Bean的属性和生命周期

常见扩展点:自定义拦截器、获取Spring容器对象、全局异常处理、类型转换器、导入配置、项目启动时、修改BeanDefinition、初始化Bean前后、初始化方法、关闭容器前、自定义作用域。

二.谈谈SpringIOC的底层实现?

前言:其实上一个问题已经把底层实现说的差不多了,这里强调一点,在说到底层实现的时候,不是说把工作原理、过程、数据结构、流程、设计模式、设计思想这些都说出来,而且只需要说出自己对它的理解和了解过的实现过程即可。

比较重要的几个点是反射,工厂(BeanFactory),设计模式

几个关键的方法如下:

CreatBeanFactory、getBean、doGetBean、createBean、doCreateBean,createBeanInstance(getDeconstructor、newInstance)、populateBean,initiializingBean

这些方法如果加了do的方法就是实际干活的方法,不加do的只是在前面套了一层,仅此而已。

简单流程如下:

1.先通过CreatBeanFactory创建出一个Bean工厂(DefaultListableBeanFactory);

2.开始循环创建对象,因为容器中的Bean默认都是单列的,所以优先通过getBean,doGetBean从容器中查找;

3.(第二步没有找到Bean)通过createBean、doCreateBean方法,以放射的方式创建对象,一般情况下使用的是无参的构造方法(getDeconstructor、newInstance);

4.进行对象的属性填充(populateBean);

5.进行其他的初始化操作(initiializingBean)。

三.谈谈Bean的生命周期?

记住下图流程即可:

但是在表述的时候,不要只谈图中的关键点,要能扩展描述,比较图相当于骨架,需要加点肉。

1.实例化Bean对象:反射的方式生成对象;

2.设置对象属性:populateBean(),循环依赖(三级缓存)问题;

3.检查Aware相关接口并设置相关方法:invokeAwareMethod(完成BeanName、BeanFactory、BeanClassLoader对象的属性设置);

4.调用BeanPostProcessor中的前置处理方法:使用较多的有ApplicationContextPostProcessor(设置ApplicationContext、Environment、ResourceLoad、EmbeddValueResolver对象);

5. 调用initmethod方法:invokeInitmethod(),判断是否实现了initializingBean接口,如果有,调用afterPropertiesSet方法,没有就不调用;

6.调用BeanPostProcessor中的后置处理方法:Spring的Aop就是在此处实现的,AbstractAutoProxyCreator;

7.注册Destuction相关的回调接口(钩子函数);

8..获取到完整的对象,可以通过getBean的方法来进行对象的获取,

9.销毁流程:(1)判断是否实现了DispoableBean接口,(2)调用DestroyMethod方法。(容器关闭的时候销毁)

四.谈谈Spring是如何解决循环依赖的问题的?

突出几个重要名词:三级缓存、提前暴露对象、Aop

总:

什么是循环依赖问题  ----- > A依赖B,B依赖A,A对象里面引用了B属性,B对象里面引用了A数据,相互引用构成闭环,就会出现循环依赖问题。

分:

先说明Bean的创建过程:实例化、初始化(填充属性),流程图如下:

1.先创建A对象,实例化A对象,此时A对象中的B属性为空,填充属性B;

2.从容器中查找B对象,如果找到了直接赋值,不存在循环依赖问题,找不到直接创建B对象;

3.实例化B对象,此时B对象中的A属性为空,填充数据A;

4.从容器中查找A对象,找不到,直接创建。

上面四个步骤是形成闭环的原因。

此时,如果仔细琢磨,会发现A对象是存在的,只不过此时的A对象不是一个完整的状态,只完成了实例化,但是未完成初始化,如果在程序的调用过程中,拥有了某个对象的引用,其实是可以在后期给它完成赋值操作,所以可以优先把一个非完整状态的对象优先赋值,等待后续操作来完成赋值,相当于提前暴露了某个不完整对象的引用,所以解决问题的核心在于实例化和初始化分开操作,这也是解决循环依赖问题的关键

当所有的对象都完成实例化和初始化操作之后,还要把完整对象放到容器中,此时在容器总存在两个对象(完成实例化但未完成初始、完整状态),因为都在容器中,所以要使用不同的Map结构来进行存储,此时就有了一级缓存和二级缓存,因为它们是互斥关系,所以,如果一级缓存中有了,那么二级缓存中就不会存在同名的对象,因为他们的查询顺序是一级、二级、三级的方式来进行查找的。一级缓存中放的是完整对象,二级缓存中放的是非完整对象

那为什么还需要三级缓存?

因为三级缓存的Value类型是ObjectFactory,是一个函数式接口,存在的意义是保证在整个容器的运行过程中同名的Bean对象只能有一个。

如果一个Bean对象需要被代理,或者说需要生成代理对象,是需要优先生成一个普通对象,再生成代理对象的,那么此时既有普通对象,又有代理对象,先使用哪个对象就是一个问题。

其实普通对象和代理对象是不能同时出现在容器中的,因此当一个对象需要被代理的时候,就要使用代理对象覆盖掉之前的普通对象,在实际的调用过程中,是没有办法确定什么时候对象被使用,所以就要求当某个对象被调用的时候,优先判断此对象是否需要被代理,类似于一种回调机制的实现,因此传入lambda表达式的时候,可以通过lambda表达式来执行对象的覆盖过程,使用getEarlyBeanReference()方法;

因此,所有的Bean对象在创建的时候都需要优先放在三级缓存中,在后续的使用过程中,如果需要被代理则返回代理对象,如果不需要被代理,直接返回普通对象。

缓存的放置时间和删除时间:

三级缓存:createBeanInstance之后(addSingletonFactory);

二级缓存:第一次从三级缓存确定对象是代理对象还是普通对象的时候,同时删除三级缓存(getSingleton);

一级缓存:生成完整对象之后放到一级缓存,然后删除二三级缓存(addSingleton)。

五.谈谈Bean Factory与FactoryBean有什么区别?

相同点:都是用来创建Bean对象的

不同点:使用BeanFactory创建对象的时候,必须要遵守严格的生命周期流程,太复杂了,如果想简单的自定义某个对象的创建,同时创建完成的对象交给Spring来管理,那么就需要实现FactoryBean接口了。

FactoryBean接口有如下几种方法:

isSingleton:是否是单列对象;

getObjectType:获取返回对象的类型;

getObject:自定义创建对象的过程(new、反射、动态代理)

两者相当于一个是复杂版,一个是简化版创建Bean,并且创建完成以后都交给Spring来管理

六.谈谈Spring中用到的设计模式?

单例模式:Bean默认都是单列的;

原型模式:指定作用域为prototype;

工厂模式:BeanFactory;

模版方法:postProcessBeanFactory、onRefresh、initPropertyValue;

策略模式:XmlBeanDefinitionReader,PropertiesBeanDefinitionReader;

观察者模式:listerner,event,multicast;

适配器模式:Adapter;

装饰者模式:BeanWrapper;

责任链模式:使用AOP的时候会先生成一个拦截器链;

代理模式:动态代理;

委托者模式:delegate;

。。。。。。。。。。

七.谈谈Spring的AOP的底层实现原理?

Aop是Ioc的一个扩展功能,先有得Ioc,再有的Aop,只是在Ioc的整个流程中新增的一个扩展点而且,BeanPostProcessor

总:

Aop概念、应用场景、动态代理;

分:

Bean的创建过程中有一个步骤可以对Bean进行扩展实现,Aop本身就是一个扩展功能,所以在BeanPostProcessor的后置处理方法中来进行实现

实现过程:

1.代理对象的创建过程(advice、切面、切点);

2.通过jdk(反射)或者cglib(生产代理类的字节码)的方法来生成代理对象;

3.在执行方法调用的时候,会调用到生成的字节码文件中,直接会找到DynamicAdvisoredInterceptor类中的intercept方法,从此方法开始执行;

4.根据之前定义好的通知,生产拦截器链;

5.从拦截器链中依次回去每一个通知开始进行执行,在执行过程中,为了方便找到下一个通知是哪个,会有一个InvocationInterceptor对象,找到时是从-1的位置依次开始查找并且执行的。

八.谈谈Spring的事务是如何回滚的?

其实也就是谈谈Spring的事务管理是如果实现的。

分析:

其实Spring事务都是通过Aop来实现的,也是Aop的一个重要应用场景,Spring里面提供了申明式事务和编程式事务,编程式事务用的很少,一般的都是用的申明式事务;其实Aop理解清楚了,事务也就理解清楚了,我们在做Aop的时候,里面有addBefore、addAfter等多种advice操作,那么我们想自定义事务怎么实现(先不管Spring是怎么实现的)?先来看一个数据库事务:

如果"进行sql操作"放在Spring事务中,相当于就是"业务逻辑"操作,如下图:

这个自定义事务就必须定义好before、after、around,还需要定义一个afterThrowing才能实现这个逻辑,这样其实挺麻烦的,有办法将它们全部合并在一个东西里面吗?那就是Spring事务。

总:

Spring的事务是由Aop来实现的,首先要根据具体的代理对象,然后按照Aop的整套流程来执行具体的操作逻辑,正常情况下要通过通知来完成核心功能,但是事务不是通过通知来实现的,而是通过一个TransactionIntercepter来实现的,然后调用invoke来实现具体的逻辑

分:

1.先做准备工作,解析各个方法上事务相关的属性,根据具体的属性来判断是否开启新事物;

2.当需要开启的时候,获取数据库连接,关闭自动提交功能,开启事务;

3.执行Sql的逻辑的操作;

4.在操作过程中,如果执行失败了,那么会通过completeTransactionAfterThrowing来完成事务的回滚操作,回滚的具体逻辑是通过doRollBack的方实现的,实现的时候也是需要先获取连接,通过连接对象回滚;

5.如果执行过程中,没有任何意外情况发生,那么通过completeTransactionAfterReturning来完成事务的提交操作,提交的具体逻辑是通过doCommit方法来实现的,实现的时候也是通过先获取连接,通过连接来提交事务;

6.当事务执行完毕之后,需要清除相关的事务信息cleanupTransactionInfo。

九.谈谈Spring事务传播?

事务有七中传播特性:

1.Required:如果当前存在事务,则加入该事务,如果不存在事务,则创建一个事务;

2.Requires_new:总是创建一个新的事务,如果当前存在事务,则挂起当前事务;

3.nested:如果当前存在事务,则在当前事务中创建一个新的嵌套事务;如果当前没有事务,则创建一个新的事务;

4.Support:如果当前存在事务,则加入该事务,如果不存在事务,则创建一个事务;

5.Not_Support:以非事务方式执行操作,如果当前存在事务,则挂起当前事务;

6.Never:以非事务方式执行操作,如果当前存在事务,则抛出异常;

7.Mandatory:如果当前存在事务,则加入到当前事务中;如果当前没有事务,则抛出异常。

某一事物嵌套另一个事物的时候怎么办?比如:A方法调用B方法,AB方法都有事务,并且传播特性不同,那么A如果有异常,B怎么办,B如果有异常,A怎么办?

总:

事务的传播特性指的是不同方法的嵌套调用过程中,事务应该如何进行处理,是用同一个事务还是不同的事务,当出现异常的时候事务会回滚还是提交,两个方法之间的相关影响的关系是什么,在日常工作中,使用比较多的是Required、Requires_new、nested。

分:

1.根据事务的分类不同,可以分为三类:

(1)支持当前事务(Required、Mandatory、Support);

(2)不支持单当前事务(Requires_new、Never、Not_Support);

(3)嵌套事务(nested);

2.如果外层方法是required,内层方法是,required,requires_new,nested,事务怎么传播;

3.如果外层方法是requires_new,内层方法是,required,requires_new,nested,事务怎么传播;

4.如果外层方法是nested,内层方法是,required,requires_new,nested,事务怎么传播;

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

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

相关文章

NAT网络地址转换——Easy IP

NAT网络地址转换 Tip: EasylP没有地址池的概念,使用接口地址作为NAT转换的公有地址。EasylP适用于不具备固定公网IP地址的场景:如通过DHCP, PPPOE拨号获取地址的私有网络出口,可以直接使用获取到的动态地址进行转换。 本次实验模拟nat协议配置 AR1配置如下&…

基于xr-frame实现微信小程序的手部、手势识别3D模型叠加和石头剪刀布游戏功能

前言 xr-frame是一套小程序官方提供的XR/3D应用解决方案,基于混合方案实现,性能逼近原生、效果好、易用、强扩展、渐进式、遵循小程序开发标准。xr-frame在基础库v2.32.0开始基本稳定,发布为正式版,但仍有一些功能还在开发&#…

【WRF-Urban】URBPARM_LCZ.TBL 查找表解释及内容

【WRF-Urban】URBPARM_LCZ.TBL 查找表解释及内容 URBPARM_LCZ.TBL 文件的作用URBPARM_LCZ.TBL 文件中的参数URBPARM_LCZ.TBL 的使用URBPARM_LCZ.TBL 文件内容如何调整或扩展 URBPARM_LCZ.TBL参考URBPARM_LCZ.TBL 文件是 WRF(天气研究与预报模型) 中用于处理 局地气候区(Loca…

nacos开启鉴权与配置加密

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 目录 前言 一、Nacos漏洞复现 1.1.查看配置 1.2.查看用户列表 1.3.注册新用户 二、Nacos开启鉴权 三、变更配置与信息加密 1.变更配置 2.信息加密 四、增强安全性 五、常见问…

AI Large Language Model

AI 的 Large Language model LLM , 大语言模型: 是AI的模型,专门设计用来处理自然语言相关任务。它们通过深度学习和庞大的训练数据集,在理解和生成自然语言文本方面表现出色。常见的 LLM 包括 OpenAI 的 GPT 系列、Google 的 PaLM 和 Meta…

前端三剑客(二):CSS

目录 1. CSS 基础 1.1 什么是 CSS 1.2 语法格式 1.3 引入方式 1.3.1 行内样式 1.3.2 内部样式 1.3.3 外部样式 1.4 CSS 编码规范 2. 选择器 2.1 标签选择器 2.2 id 选择器 2.3 class 选择器(类选择器) 2.4 复合选择器 2.5 通配符选择器 3. 常用 CSS 样式 3.1 c…

华为Ensp模拟器配置OSPF路由协议

目录 简介 实验步骤 Pc配置 路由器配置 OSPF配置 交换机配置 简介 开放式最短路径优先 (OSPF) 协议深度解析 简介 开放式最短路径优先(Open Shortest Path First, OSPF)是一种内部网关协议(IGP),用于在自治系统…

【C++】绘制内存管理的地图

生活是属于每个人自己的感受,不属于任何人的看法。 前言 这是我自己学习C的第二篇博客总结。后期我会继续把C学习笔记开源至博客上。 上一期笔记是关于C的类与对象础知识,没看的同学可以过去看看: 【C】面向对象编程的艺术之旅-CSDN博客https…

基于YOLOv8深度学习的医学影像骨折检测诊断系统研究与实现(PyQt5界面+数据集+训练代码)

本论文深入研究并实现了一种基于YOLOV8深度学习模型的医学影像骨折检测与诊断系统,旨在为医学影像中的骨折检测提供高效且准确的自动化解决方案。随着医疗影像技术的快速发展,临床医生需要从大量复杂的医学图像中精确、快速地识别病灶区域,特…

【vulhub】nginx解析漏洞(nginx_parsing_vulnerability)

1. nginx解析漏洞原理 fastcgi 在处理’.php’文件时发现文件并不存在,这时 php.ini 配置文件中cgi.fix_pathinfo1 发挥作用,这项配置用于修复路径,如果当前路径不存在则采用上层路径 (1)由于 nginx.conf的配置导致 nginx把以’.php”结尾的文件交给 fastcgi 处理,为此可以构造…

如何通过统一权限管理打破异构系统的安全屏障

企业在运营过程中面临着众多异构系统的整合挑战,这些异构系统由于其不同的技术架构、数据格式和安全机制等,给信息管理带来了诸多挑战。其中,“信息孤岛”问题尤为突出,而异构环境下的统一授权管理系统则成为解决这一问题的关键。…

阿里云IIS虚拟主机部署ssl证书

宝塔配置SSL证书用起来是很方便的,只需要在站点里就可以配置好,但是云虚拟主机在管理的时候是没有这个权限的,只提供了简单的域名管理等信息。 此处记录下阿里云(原万网)的IIS虚拟主机如何配置部署SSL证书。 进入虚拟…

Linux系列-僵尸状态

🌈个人主页:羽晨同学 💫个人格言:“成为自己未来的主人~” 进程退出 进程退出之后,代码就不会执行了,而是由PCB维护起来,我们可以通过PCB来查看退出信息。 进程退出时首先可以立即释放的就是进程对应…

DBeaver中PostgreSQL数据库显示不全的解决方法

本文介绍在DBeaver中,连接PostgreSQL后,数据库显示不全的解决方法。 最近,在DBeaver中连接了本地的PostgreSQL数据库。但是连接后打开这个数据库时发现,其所显示的Databases不全。如下图所示,Databases只显示了一个pos…

pycharm中配置pyqt5

pycharm中配置pyqt5 Python提供了多种图形界面库,包括但不限于Tkinter、PyQt、wxPython、Kivy等。Tkinter由于其轻量级和跨平台特性,通常作为入门首选。PyQt和wxPython则提供了更多的控件和更强大的功能,适合于需要复杂用户界面的应用程序。…

SpringBoot+Vue 2 多方法实现(图片/视频/报表)文件上传下载,示例超详细 !

目录 一、主流方法介绍 1. Base 64 2. 二进制流传输 3. multipart/form-data 4. FTP/SFTP 5. 云存储服务API 二、multipart/form-data 方式上传单个文件 1、前端部分 2、后端部分 三、multipart/form-data 方式上传多个文件 1、前端部分 2、后端部分 四、Base 64 方…

数据库迁移--laravel进阶篇

本地开发中的数据库和线上发布的数据库是不一样的,每进行一个线上版本的更新,很可能也涉及大量数据库的改动,那么这些数据库的改动在laravel中可以使用数据库迁移来处理。 比如我想创建一张flights数据表 执行php artisan make:migration create_flights_table命令就能自动生…

uni-app 修改复选框checkbox选中后背景和字体颜色

编写css(注意:这个样式必须写在App.vue里) /* 复选框 */ /* 复选框-圆角 */ checkbox.checkbox-round .wx-checkbox-input, checkbox.checkbox-round .uni-checkbox-input {border-radius: 100rpx; } /* 复选框-背景颜色 */ checkbox.checkb…

java实现ModbusCRC16校验

1. 目的 电流数据采集器是RS485 Modbus协议,想通过java实现串口数据的采集,因为涉及到串口通信的CRC校验,所以需要通过java来实现对采集的电流值进行校验,确保每次读到的电流值都是正常的。 2. 什么是ModbusCRC16校验 Modbus协议…

aws上安装ssm-agent

aws-cloudwatch 连接机器 下载ssm-agent aws-ec2 安装ssm-agent aws-linux安装ssm-agent 使用 SSM 代理查找 AMI 预装 先运行:systemctl status amazon-ssm-agent 查看sshm-agent的状态。 然后安装提示,执行 systemctl start amazon-ssm-agent 启动即…