当前位置: 首页 > news >正文

Spring后端框架复习总结

之前写的博客太杂,最近想把后端框架的知识点再系统的过一遍,主要是Spring Boot和Mybatis相关,带着自己的理解使用简短的话把一些问题总结一下,尤其是开发中和面试中的高频问题,基础知识点可以参考之前写java后端专栏,这篇不再赘述。

目录

  • Spring
    • 什么是AOP?底层原理?
    • 事务底层原理?多线程事务能不能保证一致性?
    • 事务失效场景?
    • Bean的生命周期及常用自定义方法
    • 有两个相同id的Bean会报错吗?
    • 循环依赖相关
    • Spring MVC是什么,核心是什么,它的执行流程?
    • Spring MVC的控制器(bean)是不是单例模式(是不是线程安全)?存在什么问题?如何解决?
    • 起步依赖、自动配置原理;yml等配置文件的配置优先级
    • IOC的工作流程;控制反转与依赖注入原理
    • 常见注解有哪些? @Autowird 与 @Resource区别;@Component和@Bean区别;@Conditional作用
    • 过滤器与拦截器的区别
    • 如何解决跨域问题?
    • 设计模式
  • Mybaits
    • MyBatis执行流程
    • Mybatis是否支持延迟加载?底层原理是什么?
    • 一级、二级缓存;二级缓存什么时候会清理缓存中的数据
    • Mybatis实现分页查询的几种方式

Spring

什么是AOP?底层原理?

详细介绍–>SpringBoot 事务与AOP

什么是AOP?

aop是面向切面编程,在spring中用于将那些与业务无关,但却对多个对象产生影响的公共行为和逻辑,抽取公共模块复用,降低耦合,一般比如可以做为公共日志保存,事务处理等

我们当时在后台系统中,就是使用aop来记录了系统的操作日志。主要思路是这样的,使用aop中的环绕通知+切点表达式,这个表达式就是要找到要记录日志的方法,然后通过环绕通知的参数获取请求方法的参数,比如类信息、方法信息、注解、请求方式等,获取到这些参数以后,保存到数
据库。

AOP的底层原理?

Spring AOP中的动态代理主要有两种方式,JDK动态代理和CGLIB动态代理。

  • JDK动态代理只提供接口的代理,不支持类的代理
    • JDK会在运行时为目标类生成一个动态代理类$proxy*.class .
    • 该代理类是实现了接目标类接口,并且代理类会实现接口所有的方法增强代码
    • 调用时先去调用处理类进行增强,再通过反射的方式进行调用目标方法。从而实现AOP

  • 如果代理类没有实现接口,那么Spring AOP会选择使用CGLIB来动态代理目标类。
    • CGLIB的底层是通过ASM(一种用于直接生成或修改字节码的框架,全称为 “Abstract Syntax Notation One”)在运行时动态的生成目标类的一个子类。(还有其他相关类)会生成多个。并且会重写父类所有的方法增强代码,
    • 调用时先通过代理类进行增强,再直接调用父类对应的方法进行调用目标方法。从而实现AOP。
      • CGLIB是通过继承的方式做的动态代理,因此如果某个类被标记为final,那么它是无法使用CGLIB做动态代理的。
      • CGLIB除了生成目标子类代理类,还有一个FastClass(路由类),可以(但不是必须))让本类方法调用进行增强,而不会像jdk代理那样本类方法调用增强会失效

  • jck动态代理生成类速度快,调用慢,cglib生成类速度慢,但后续调用快。就二者的效率来说,大部分情况都是 JDK 动态代理更优秀,随着 JDK 版本的升级,这个优势更加明显。


事务底层原理?多线程事务能不能保证一致性?

详细介绍–>SpringBoot 事务与AOP

spring实现的事务本质就是AOP完成,对方法前后进行拦截,在执行方法之前开启事务,在执行完目标方法之后根据执行情况提交或者回滚事务。其中AOP底层是基于JDK动态代理和cglib动态代理实现的,这个上面有介绍。

Spring多线程事务能不能保证一致性

假设A方法被声明了@Transactional,然后在A方法里new一个线程,去执行B方法,那么这种情况下A和B能保证原子性或者数据一致性么?A失败了B会回滚吗?或者B失败了A会回滚吗?

答案:不能。因为Spring底层是使用ThreadLocal来保存事务信息的比如数据库连接Connection,所以一个线程永远只能有一个事务,Spring的事务是无法实现事务一致性的。
解决办法:可以自己解决,比如通过编程式的事务,自己控制提交和回滚,或者说通过分布式事务的思路,2PC,3PC,SAGA,MQ的消息最终一致性都可以解决。


编程式事务:这种方式是通过编程的方式来控制事务的提交和回滚。在Spring中,可以使用TransactionTemplate或者PlatformTransactionManager来实现。例如,你可以在A方法中创建一个新的事务,然后在B方法中使用相同的事务。如果A或B中有任何异常,你可以捕获这个异常并决定是否回滚事务。这种方式需要你手动管理事务,包括开始事务、提交事务、回滚事务等。


分布式事务:这是一种更复杂的解决方案,通常用于处理跨多个数据库或服务的事务。这种方法包括以下几种策略:
2PC(两阶段提交):这是一种原子性协议,它保证了所有参与者要么都提交事务,要么都不提交。它分为两个阶段:准备阶段和提交阶段。在准备阶段,所有参与者都会被询问是否可以提交事务,只有当所有参与者都同意提交事务时,才会进入提交阶段。否则,事务将被回滚。
3PC(三阶段提交):这是两阶段提交的改进版,它添加了一个超时机制,以防止在等待其他参与者响应时发生阻塞。
SAGA:这是一种长寿命事务的解决方案,它将一个大事务分解为多个小事务,每个小事务都可以独立地提交或回滚。如果某个小事务失败,SAGA会执行一系列的补偿操作来保证数据的一致性。
MQ(消息队列):这是一种最终一致性的解决方案,它使用消息队列来保证事务的一致性。如果A方法执行成功,它会发送一个消息到消息队列,然后B方法会监听这个消息队列,当它收到消息时,就会执行相应的操作。



事务失效场景?

详细介绍–>SpringBoot 事务与AOP

Spirng通过@transactional注解来进行事务控制,但很多场景会导致事务失效。

第一个,如果方法上异常捕获处理,自己try catch处理了异常,没有抛出,就会导致事务失效,所以一般处理了异常以后,别忘了抛出去就行了

第二个,如果报RuntimeException以外的错也会导致事务失效,若在@Transactional上配置rollbackFor属性为Exception,这样别管是什么异常,都会回滚事务

默认情况下,只有出现RuntimeException(运行时异常)才会回滚事务。假如我们想让所有的异常都回滚,需要来配置@Transactional注解当中的rollbackFor属性,通过rollbackFor这个属性可以指定出现何种异常类型回滚事务

第三,如果方法是private修饰的,也会导致事务失效,因为AOP底层是基于cglib动态代理实现的,子类是不能重载父类的private方法的,所以无法很好的利用代理,会导致@Transactional失效。

ps:因为Spring事务是基于代理来实现的,所以某个加了@Transactional的方法只有是代理对象调用时,那么这个注解才会生效,所以如果是被代理对象来调用这个方法,那么@Transactional是不会生效的。

第四,@Transactional注解在了final或static修饰的方法上。因为被final修饰的方法是无法被重写的,所以代理对象是无法调用的。而static修饰的方法属于类对象不属于对象实例,所以代理对象也是无法调用的。

第五,当前类没有被Spring容器所管理,没有配置成bean。如果当前类没有被Spring 容器所管理,那么Spring就无法为该类生成代理对象,从而Spring 的事务会失效。

请添加图片描述

第六,同一个类中方法的调用,导致的 AOP失效,从而导致@Transactional注解失效。这也是我们开发中最容易犯错的一种场景。

请添加图片描述

同一个类中的方法调用,属于this 调用,并不会使用代理对象,所以 AOP会失效。没有办法通过动态代理给你进行增强。不过,该问题可以使用如下方式来解决,因为我们从spring容器中自动装配的bean假如实现了声明式事务或者AOP,那么就会为你创建动态代理。

请添加图片描述

除了上面的自动装配,还可以这样:((UserService)AopContext.currentProxy()).methodB()
也可以拿到当前的动态代理对象,这个方法的原理是当我们调用了一个动态代理的方法(methodA()),会把当前的动态代理对象存入到currentProxy的ThreadLocal中,那么此时再通过AopContext获得currentProxy,就可以拿到当前正在调用的动态代理对象,这种写法呢比自己注入进来更加优雅,且不会存在循环依赖问题。

第七,多个事务方法不在同一个线程内执行。如下代码片段中,事务方法addUser()中调用了另外一个事务方法roleService.addRole(),注意,这两个方法不是在同一个线程中执行的!这会导致什么问题呢?我们上面刚刚说过了,spring不能保证多线程下的事务一致性,这两个事务方法获取到的数据库连接是2个不同的数据库连接!不同的数据库连接会导致事务失效!解决办法在上面的Spring多线程事务能不能保证一致性中有介绍。

请添加图片描述

请添加图片描述



Bean的生命周期及常用自定义方法

详细介绍–>SpingBoot原理

在这里插入图片描述

简单来说分为五步:

  • 1.实例化:当容器需要初始化一个尚未初始化的Bean,或者初始化Bean时需要注入另一个尚未初始化的依赖时,容器会调用doCreateBean()方法进行实例化。实际上,这是通过反射的方式创建出一个Bean对象。
  • 2.属性赋值:Bean实例创建完成后,接下来是为这个Bean对象进行属性填充,也就是注入这个Bean依赖的其他Bean对象。
  • 3.初始化 :在属性填充完成后,进行Bean的初始化操作。初始化阶段包括以下几个步骤:
    • 3.1.执行Aware接口的方法:Spring会检测该对象是否实现了xxx Aware接口,通过Aware类型的接口,可以让我们获取Spring容器的一些资源。例如,实现BeanNameAware接口可以获取到Bean的名称,实现BeanFactoryAware接口可以获取到工厂对象BeanFactory等。
    • 3.2.判断Bean是否实现了InitializingBean接口,如果实现了,将会执行InitializingBean的afterPropertiesSet()初始化方法。
    • 3.3.执行用户自定义的初始化方法(如果有指定的话),如init-method等。
    • 3.4.执行BeanPostProcessor的后置处理方法postProcessAfterInitialization()。
  • 4.使用:初始化完成后,Bean就成功创建了,之后就可以使用这个Bean。
  • 5.销毁:当Bean不再需要时,会进行销毁操作。销毁阶段包括以下步骤:
    • 5.1.判断Bean是否实现了DestructionAwareBeanPostProcessor接口,如果实现了,则会执行DestructionAwareBeanPostProcessor后置处理器的销毁回调方法。
    • 5.2.判断Bean是否实现了DisposableBean接口,如果实现了,将会调用其实现的destroy()方法。
    • 5.3后判断这个Bean是否配置了destroy-method等自定义的销毁方法,如果有配置,则会自动调用其配置的销毁方法。

如果详细一点介绍的话可以分为五个阶段:

创建前准备:Bean在开始加载之前要从上下文和一些配置中去解析并且查找Bean有关扩展的实现,比如像init-method,容器在初始化Bean的时候或调用的一个方法,destroy-method,容器在销毁Bean的时候会调用的一些方法,以及BeanFactoryPostProcessor这一类的Bean加载过程中的一些前置和后置的一些处理扩展实现,这些类和配置其实是Springr提供给开发者用来去实现Bean加载过程中的一些扩展,在很多和Spring集成的中间件也比较常见,比如Dubbo,这样一些中间件。

创建实例化:这个阶段主要作用是通过反射去创建Bean的实例对象,并且会扫描和解析Bean声明的一些属性

依赖注入:如果被实例化的Bean存在依赖其他Bean对象的一些情况,则需要对这些依赖的Bean进行对象注入,比如常见的@Autowired,以及setter注入等这样一些配置形式,

相关文章:

Spring后端框架复习总结

之前写的博客太杂,最近想把后端框架的知识点再系统的过一遍,主要是Spring Boot和Mybatis相关,带着自己的理解使用简短的话把一些问题总结一下,尤其是开发中和面试中的高频问题,基础知识点可以参考之前写java后端专栏,这篇不再赘述。 目录 Spring什么是AOP?底层原理?事务…...

基于Llama Index构建RAG应用

前言 Hello,大家好,我是GISer Liu😁,一名热爱AI技术的GIS开发者,本文参与活动是2024 DataWhale AI夏令营;😲 在本文中作者将通过: Gradio、Streamlit和LlamaIndex介绍 LlamaIndex 构…...

SSLRec代码分析

文章目录 encoder-models-general_cfautocf.py data_utilsdata_handler_general_cf.py输入输出说明使用方法 trainertuner.py encoder-models-general_cf autocf.py import torch as t # 导入PyTorch并重命名为t from torch import nn # 从PyTorch导入神经网络模块 import …...

第四节shell条件测试(1)(2)

一,命令执行结果判定 &&在命令执行后如果没有任何报错时会执行符号后面的动作 ||在命令执行后如果命令有报错会执行符号后的动作 示例: vim lee.sh #!/bin/bash ls /mnt/file &> /dev/null &&{echo /mnt/filr is not existecho no }||{echo /mnt/fi…...

申请https证书的具体流程

申请HTTPS证书的具体流程通常涉及以下步骤,不过请注意,具体细节可能因不同的证书颁发机构(CA)而有所差异: 1、确定证书类型: 证书类型:根据需求选择合适的SSL证书类型。常见的有DV(…...

IP溯源工具--IPTraceabilityTool

工具地址:xingyunsec/IPTraceabilityTool: 蓝队值守利器-IP溯源工具 (github.com) 工具介绍: 在攻防演练期间,对于值守人员,某些客户要求对攻击IP都进行分析溯源,发现攻击IP的时候,需要针对攻击IP进行分析…...

字节抖音电商 后端开发岗位 一面

笔者整理答案,以供参考 自我介绍 项目(20分钟) RocketMQ延时消息的底层实现 回答: 延时消息的实现主要依赖于RocketMQ中的定时任务机制。消息被发送到Broker时,会先存储在一个特定的延时消息队列中。Broker会定时扫…...

前端开发日记——在MacBook上配置Vue环境

前言 大家好,我是来自CSDN的寄术区博主PleaSure乐事。今天是开始学习vue的第一天,我使用的编译器是vscode,浏览器使用的是谷歌浏览器,后续会下载webstorm进行使用,当前学习阶段使用vscode也是可以的,不用担…...

测试开发面经总结(三)

TCP三次握手 TCP 是面向连接的协议,所以使用 TCP 前必须先建立连接,而建立连接是通过三次握手来进行的。 一开始,客户端和服务端都处于 CLOSE 状态。先是服务端主动监听某个端口,处于 LISTEN 状态 客户端会随机初始化序号&…...

开始构建我们自己的大语言模型:数据处理部分

关注本专栏(NLP简论:手搓大语言模型实践) 继续学习从头编写、训练自己的大语言模型。 接上集,本章我们将深入说一下大语言模型数据处理部分的细节,并直接提供本部分的完整代码。 【配套资源】 暂时的词汇表&#xff1…...

springboot系列十: 自定义转换器,处理JSON,内容协商

文章目录 自定义转换器基本介绍应用实例查看源码注意事项和细节 处理JSON需求说明应用实例 内容协商基本介绍应用实例debug源码优先返回xml注意事项和细节 ⬅️ 上一篇: springboot系列九: 接收参数相关注解 🎉 欢迎来到 springboot系列十: 自定义转换器&#xff0c…...

C++(new与delete操作符)

C中的new与delete new 与 delete定位new表达式 new 与 delete 在C中需要动态申请内存空间时需要使用 new 与 delete 这两个操作符 #include <iostream> using namespace std; int main() {int* p1 new int;//开辟一块int类型大小的空间给p1int* p2 new int(1);//开辟…...

STM32智能工业自动化监控系统教程

目录 引言环境准备智能工业自动化监控系统基础代码实现&#xff1a;实现智能工业自动化监控系统 4.1 数据采集模块 4.2 数据处理与控制模块 4.3 通信与网络系统实现 4.4 用户界面与数据可视化应用场景&#xff1a;工业自动化与管理问题解决方案与优化收尾与总结 1. 引言 智能…...

WPF设置欢迎屏幕,程序启动过度动画

当主窗体加载时间过长&#xff0c;这时候基本都会想添加一个等待操作来响应用户点击&#xff0c;提高用户体验。下面我记录两个方法&#xff0c;一点拙见&#xff0c;仅供参考。 方法1:在App类中使用SplashScreen类。 protected override void OnStartup(StartupEventArgs e)…...

Flink实时开发添加水印的案例分析

在Flink中&#xff0c;处理时间序列数据时&#xff0c;通常需要考虑事件时间和水印&#xff08;watermarks&#xff09;的处理。以下是修改前后的代码对比分析&#xff1a; 修改前的代码&#xff1a; val systemDS unitDS.map(dp > {dp.setDeviceCode(DeviceCodeEnum.fro…...

收银系统源码-线上商城diy装修

线下线上一体化收银系统越来越受门店重视&#xff0c;尤其是连锁多门店&#xff0c;想通过线下线上相互带动&#xff0c;相互引流&#xff0c;提升门店营业额。商城商城如何装修呢&#xff1f; 1.收银系统开发语言 核心开发语言: PHP、HTML5、Dart后台接口: PHP7.3后合管理网…...

Linux中nohup(no hang up)不挂起,用于在系统后台不挂断地运行命令,即使退出终端也不会影响程序的运行。

nohup的英文全称是 no hang up&#xff0c;即“不挂起”。这个命令在Linux或Unix系统中非常有用&#xff0c;主要用于在系统后台不挂断地运行命令&#xff0c;即使退出终端也不会影响程序的运行。默认情况下&#xff08;非重定向时&#xff09;&#xff0c;nohup会将输出写入一…...

【.NET全栈】ASP.NET开发Web应用——站点导航技术

文章目录 前言一、站点地图1、定义站点地图文件2、使用SiteMapPath控件3、SiteMap类4、URL地址映射 二、TreeView控件1、使用TreeView控件2、以编程的方式添加节点3、使用TreeView控件导航4、绑定到XML文件5、按需加载节点6、带复选框的TreeView控件 三、Menu控件1、使用Menu控…...

docker 容器内部UI映射host

方法有很多&#xff0c; 目前我总计一个我自己尝试成功的方法&#xff0c;通过xpra。 Xpra可以看作是screen或tmux的图形版本&#xff0c;支持远程X11应用程序的显示和交互。 在远程服务器上&#xff0c;安装Xpra&#xff1a; sudo apt-get install xpra启动Xpra服务器会话&…...

数仓面试题——DWS层新增维度字段需求

前言 在数据仓库开发中&#xff0c;数据仓库的设计和维护一直是一个备受关注的话题。随着业务需求的不断变化&#xff0c;数据仓库的结构也需要随之调整。 面试过程中&#xff0c;多次被提问&#xff1a;当DWS构建好后&#xff0c;突然来了一个新的需求&#xff0c;需要添加某个…...

iOS 26 携众系统重磅更新,但“苹果智能”仍与国行无缘

美国西海岸的夏天&#xff0c;再次被苹果点燃。一年一度的全球开发者大会 WWDC25 如期而至&#xff0c;这不仅是开发者的盛宴&#xff0c;更是全球数亿苹果用户翘首以盼的科技春晚。今年&#xff0c;苹果依旧为我们带来了全家桶式的系统更新&#xff0c;包括 iOS 26、iPadOS 26…...

label-studio的使用教程(导入本地路径)

文章目录 1. 准备环境2. 脚本启动2.1 Windows2.2 Linux 3. 安装label-studio机器学习后端3.1 pip安装(推荐)3.2 GitHub仓库安装 4. 后端配置4.1 yolo环境4.2 引入后端模型4.3 修改脚本4.4 启动后端 5. 标注工程5.1 创建工程5.2 配置图片路径5.3 配置工程类型标签5.4 配置模型5.…...

为什么需要建设工程项目管理?工程项目管理有哪些亮点功能?

在建筑行业&#xff0c;项目管理的重要性不言而喻。随着工程规模的扩大、技术复杂度的提升&#xff0c;传统的管理模式已经难以满足现代工程的需求。过去&#xff0c;许多企业依赖手工记录、口头沟通和分散的信息管理&#xff0c;导致效率低下、成本失控、风险频发。例如&#…...

鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院查看报告小程序

一、开发环境准备 ​​工具安装​​&#xff1a; 下载安装DevEco Studio 4.0&#xff08;支持HarmonyOS 5&#xff09;配置HarmonyOS SDK 5.0确保Node.js版本≥14 ​​项目初始化​​&#xff1a; ohpm init harmony/hospital-report-app 二、核心功能模块实现 1. 报告列表…...

三体问题详解

从物理学角度&#xff0c;三体问题之所以不稳定&#xff0c;是因为三个天体在万有引力作用下相互作用&#xff0c;形成一个非线性耦合系统。我们可以从牛顿经典力学出发&#xff0c;列出具体的运动方程&#xff0c;并说明为何这个系统本质上是混沌的&#xff0c;无法得到一般解…...

成都鼎讯硬核科技!雷达目标与干扰模拟器,以卓越性能制胜电磁频谱战

在现代战争中&#xff0c;电磁频谱已成为继陆、海、空、天之后的 “第五维战场”&#xff0c;雷达作为电磁频谱领域的关键装备&#xff0c;其干扰与抗干扰能力的较量&#xff0c;直接影响着战争的胜负走向。由成都鼎讯科技匠心打造的雷达目标与干扰模拟器&#xff0c;凭借数字射…...

【C++从零实现Json-Rpc框架】第六弹 —— 服务端模块划分

一、项目背景回顾 前五弹完成了Json-Rpc协议解析、请求处理、客户端调用等基础模块搭建。 本弹重点聚焦于服务端的模块划分与架构设计&#xff0c;提升代码结构的可维护性与扩展性。 二、服务端模块设计目标 高内聚低耦合&#xff1a;各模块职责清晰&#xff0c;便于独立开发…...

零基础在实践中学习网络安全-皮卡丘靶场(第九期-Unsafe Fileupload模块)(yakit方式)

本期内容并不是很难&#xff0c;相信大家会学的很愉快&#xff0c;当然对于有后端基础的朋友来说&#xff0c;本期内容更加容易了解&#xff0c;当然没有基础的也别担心&#xff0c;本期内容会详细解释有关内容 本期用到的软件&#xff1a;yakit&#xff08;因为经过之前好多期…...

JAVA后端开发——多租户

数据隔离是多租户系统中的核心概念&#xff0c;确保一个租户&#xff08;在这个系统中可能是一个公司或一个独立的客户&#xff09;的数据对其他租户是不可见的。在 RuoYi 框架&#xff08;您当前项目所使用的基础框架&#xff09;中&#xff0c;这通常是通过在数据表中增加一个…...

Python基于历史模拟方法实现投资组合风险管理的VaR与ES模型项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档&#xff09;&#xff0c;如需数据代码文档可以直接到文章最后关注获取。 1.项目背景 在金融市场日益复杂和波动加剧的背景下&#xff0c;风险管理成为金融机构和个人投资者关注的核心议题之一。VaR&…...