从0到1深入解读Spring AOP、 IOC、 事务的属性,传播行为,隔离级别
mhr18 2025-06-15 17:38 19 浏览 0 评论
AOP:面向切面编程
即在一个功能模块中新增其他功能,比方说你要下楼取个快递,你同事对你说帮我也取一下
呗,你就顺道取了。在工作中如果系统中有些包和类中没有使用 AOP,例如日志,事务和异常处理,那么就必须在每个类和方法中去实现它们。 代码纠缠每个类和方法中都包含日志,事务以及异常处理甚至是业务逻辑。在一个这样的方法中,很难分清代码中实际做的是什么处理。AOP 所做的就是将所有散落各处的事务代码集中到一个事务切面中。
场景
比方说我现在要弄一个日志,记录某些个接口调用的方法时间。使用 Aop 我可以在这个接
口前插入一段代码去记录开始时间,在这个接口后面去插入一段代码记录结束时间。
又或者你去访问数据库,而你不想管事务(太烦),所以,Spring 在你访问数据库之前,自
动帮你开启事务,当你访问数据库结束之后,自动帮你提交/回滚事务!
异常处理你可以开启环绕通知,一旦运行接口报错,环绕通知捕获异常跳转异常处理页面。
动态代理
Spring AOP 使用的动态代理,所谓的动态代理就是说 AOP 框架不会去修改字节码,而是在内存中临时为方法生成一个 AOP 对象,这个 AOP 对象包含了目标对象的全部方法,并且在特定的切点做了增强处理,并回调原对象的方法。它的动态代理主要有两种方式,JDK 动态代理和 CGLIB 动态代理。
JDK 动态代理通过反射来接收被代理的类,并且要求被代理的类必须实现一个接口。JDK 动态代理的核心是 InvocationHandler 接口和 Proxy 类。如果目标类没有实现接口,那么 Spring AOP 会选择使用 CGLIB 来动态代理目标类。
CGLIB 是一个代码生成的类库,可以在运行时动态的生成某个类的子类,注意,CGLIB 是通过继承的方式做的动态代理,因此如果某个类被标记为 final,那么它是无法使用 CGLIB 做动态代理的。
IOC:依赖注入或者叫做控制反转
正常情况下我们使用一个对象时都是需要 new Object()的。而 ioc 是把需要使用的对象提前创建好,放到 spring 的容器里面。所有需要使用的类都会在 spring 容器中登记,告诉 spring 你是个什么东西,你需要什么东西,然后 spring 会在系统运行到适当的时候,把你要的东西主动给你,同时也把你交给其他需要你的东西。所有的类的创建、销毁都由 spring 来控制,也就是说控制对象生存周期的不再是引用它的对象,而是 spring。DI(依赖注入)其实就是 IOC 的另外一种说法,其实它们是同一个概念的不同角度描述。
场景:
正常情况下我们使用一个对象时都是需要 new Object() 的。而 ioc 是把需要使用的对象提前创建好,放到 spring 的容器里面。需要使用的时候直接使用就行,而且可以设置单例或多例,非常灵活。
我们在 service想调用另外一个 service 的方法,不需要去 new 了,直接把它交给 spring管理,然后用注解的方式引入就能使用。
IOC 三种注入方式
(1)XML:Bean 实现类来自第三方类库,例如 DataSource 等。需要命名空间等配置,例如:context,aop,mvc。
(2)注解:在开发的类使用@Controller,@Service 等注解
(3)Java 配置类:通过代码控制对象创建逻辑的场景。例如:自定义修改依赖类库。
什么是事务?
事务是访问并可能更新数据库中各种数据项的一个程序执行单元。
Spring 事务与数据库事务关系?
Spring 的事务是对数据库的事务的封装,最后本质的实现还是在数据库,假如数据库不支持事务的话,Spring 的事务是没有作用的。所以说 Spring 事务的底层依赖 MySQL 的事务,Spring是在代码层面利用 AOP 实现,执行事务的时候使用 TransactionInceptor 进行拦截,然后处理。
本质是对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务,执行完目标
方法之后根据执行的情况提交或者回滚。
属性(特性)
A(原子性):要么全部完成,要么完全不起作用
C(一致性):一旦事务完成(不管成功还是失败),业务处于一致的状态,而不会是部分完
成,部分失败。
I(隔离性):多事务会同时处理相同的数据,因此每个事务都应该与其他事务隔离开来,防止
数据损坏。
D(持久性):一旦事务完成,无论发生什么系统错误,它的结果都不应该受到影响,事务的
结果被写到持久化存储器中。
什么叫事务传播行为?
传播,至少有两个东西,才可以发生传播。单体不存在传播这个行为。事务传播行为就是当
一个事务方法被另一个事务方法调用时,这个事务方法应该如何进行。
Spring 支持 7 中事务传播行为
propagation_required(需要传播):当前没有事务则新建事务,有则加入当前事务
propagation_supports(支持传播):支持当前事务,如果当前没有事务则以非事务方式执行
propagation_mandatory(强制传播):使用当前事务,如果没有则抛出异常
propagation_nested(嵌套传播):如果当前存在事务,则在嵌套事务内执行,如果当前没
有事务,则执行需要传播行为。
propagation_never(绝不传播):以非事务的方式执行,如果当前有事务则抛出异常
propagation_requires_new(传播需要新的):新建事务,如果当前有事务则把当前事务挂起
propagation_not_supported(不支持传播):以非事务的方式执行,如果当前有事务则把当
前事务挂起
数据库事务的隔离级别
数据库事务的隔离级别有 4 个,由低到高依次为 Read uncommitted、Read committed、
Repeatable read、Serializable,这四个级别可以逐个解决脏读、不可重复读、幻读这几类问
题。
√: 可能出现 ×: 不会出现
注意:我们讨论隔离级别的场景,主要是在多个事务并发的情况下,因此,接下来的讲解都
围绕事务并发。
Read uncommitted 读未提交
公司发工资了,领导把 20000 元打到廖志伟的账号上,但是该事务并未提交,而廖志伟正好去查看账户,发现工资已经到账,是 20000 元整,非常高兴。可是不幸的是,领导发现发廖志伟的工资金额不对,是 16000 元,于是迅速回滚了事务,修改金额后,将事务提交,最后廖志伟实际的工资只有 16000 元,廖志伟空欢喜一场。
出现上述情况,即我们所说的脏读,两个并发的事务,“事务A:领导给廖志伟发工资”、
“事务B:廖志伟查询工资账户”,事务B 读取了事务A 尚未提交的数据。当隔离级别设置
为 Read uncommitted 时,就可能出现脏读,如何避免脏读,请看下一个隔离级别。
Read committed 读提交
廖志伟拿着工资卡去消费,系统读取到卡里确实有 2000 元,而此时她的老婆也正好在网上
转账,把廖志伟工资卡的 2000 元转到另一账户,并在廖志伟之前提交了事务,当廖志伟扣
款时,系统检查到廖志伟的工资卡已经没有钱,扣款失败,廖志伟十分纳闷,明明卡里有钱,
为何…
出现上述情况,即我们所说的不可重复读,两个并发的事务,“事务A:廖志伟消费”、“事
务B:廖志伟的老婆网上转账”,事务 A 事先读取了数据,事务B 紧接了更新了数据,并提
交了事务,而事务 A 再次读取该数据时,数据已经发生了改变。当隔离级别设置为 Read
committed 时,避免了脏读,但是可能会造成不可重复读。大多数数据库的默认级别就是 Read
committed,比如 Sql Server , Oracle。如何解决不可重复读这一问题,请看下一个隔离级别。
Repeatable read 重复读
当廖志伟拿着工资卡去消费时,一旦系统开始读取工资卡信息(即事务开始),廖志伟的老
婆就不可能对该记录进行修改,也就是廖志伟的老婆不能在此时转账。这就避免了不可重复
读。廖志伟的老婆工作在银行部门,她时常通过银行内部系统查看廖志伟的信用卡消费记录。
有一天,她正在查询到廖志伟当月信用卡的总消费金额(select sum(amount) from transaction
where month = 本月)为 80 元,而廖志伟此时正好在外面胡吃海喝后在收银台买单,消费
1000 元,即新增了一条 1000 元的消费记录(insert transaction … ),并提交了事务,随后
廖志伟的老婆将廖志伟当月信用卡消费的明细打印到 A4 纸上,却发现消费总额为 1080 元,廖志伟的老婆很诧异,以为出现了幻觉,幻读就这样产生了。当隔离级别设置为 Repeatableread 时,可以避免不可重复读,但会出现幻读。注:MySQL 的默认隔离级别就是 Repeatableread。
Serializable 序列化
Serializable 是最高的事务隔离级别,同时代价也花费最高,性能很低,一般很少使用,在该
级别下,事务顺序执行,不仅可以避免脏读、不可重复读,还避免了幻像读。
相关推荐
- Java面试题及答案总结(2025版)
-
大家好,我是Java面试陪考员最近很多小伙伴在忙着找工作,给大家整理了一份非常全面的Java面试题及答案。涉及的内容非常全面,包含:Redis、Linux、SpringBoot、Spring、MySQ...
- Java面试题及答案最全总结(2025春招版)
-
大家好,我是Java面试分享最近很多小伙伴在忙着找工作,给大家整理了一份非常全面的Java面试题及答案。涉及的内容非常全面,包含:Spring、MySQL、JVM、Redis、Linux、Spring...
- Java面试题及答案最全总结(2025版持续更新)
-
大家好,我是Java面试陪考员最近很多小伙伴在忙着找工作,给大家整理了一份非常全面的Java面试题及答案。涉及的内容非常全面,包含:Spring、MySQL、JVM、Redis、Linux、Sprin...
- 蚂蚁金服面试题(附答案)建议收藏:经典面试题解析
-
前言最近编程讨论群有位小伙伴去蚂蚁金服面试了,以下是面试的真题,跟大家一起来讨论怎么回答。点击上方“捡田螺的小男孩”,选择“设为星标”,干货不断满满1.用到分布式事务嘛?为什么用这种方案,有其他方案...
- 测试工程师面试必问的十道题目!全答上来的直接免试
-
最近参加运维工程师岗位的面试,笔者把自己遇到的和网友分享的一些常见的面试问答收集整理出来了,希望能对自己和对正在准备面试的同学提供一些参考。一、Mongodb熟悉吗,一般部署几台?部署过,没有深入研究...
- 10次面试9次被刷?吃透这500道大厂Java高频面试题后,怒斩offer
-
很多Java工程师的技术不错,但是一面试就头疼,10次面试9次都是被刷,过的那次还是去了家不知名的小公司。问题就在于:面试有技巧,而你不会把自己的能力表达给面试官。应届生:你该如何准备简历,面试项目和...
- java高频面试题整理
-
【高频常见问题】1、事务的特性原子性:即不可分割性,事务要么全部被执行,要么就全部不被执行。一致性或可串性:事务的执行使得数据库从一种正确状态转换成另一种正确状态隔离性:在事务正确提交之前,不允许把该...
- 2025 年最全 Java 面试题,京东后端面试面经合集,答案整理
-
最近京东搞了个TGT计划,针对顶尖青年技术天才,直接宣布不设薪资上限。TGT计划面向范围包括2023年10月1日到2026年9月30日毕业的海内外本硕博毕业生。时间范围还...
- idGenerator测评
-
工作中遇到需要生成随机数的需求,看了一个个人开发的基于雪花算法的工具,今天进行了一下测评(测试)。idGenerator项目地址见:https://github.com/yitter/IdGenera...
- 2024年开发者必备:MacBook Pro M1 Max深度体验与高效工作流
-
工作机器我使用的是一台16英寸的MacBookProM1Max。这台电脑的表现堪称惊人!它是我用过的最好的MacBook,短期内我不打算更换它。性能依然出色,即使在执行任务时也几乎听不到风扇的...
- StackOverflow 2022 年度调查报告
-
一个月前,StackOverflow开启了2022年度开发者调查,历时一个半月,在6月22日,StackOverflow正式发布了2022年度开发者调查报告。本次报告StackO...
- 这可能是最全面的SpringDataMongoDB开发笔记
-
MongoDB数据库,在最近使用越来越广泛,在这里和Java的开发者一起分享一下在Java中使用Mongodb的相关笔记。希望大家喜欢。关于MongoDB查询指令,请看我的上一篇文章。SpringD...
- Mac M2 本地部署ragflow
-
修改配置文件Dockerfile文件ARGNEED_MIRROR=1//开启国内镜像代理docker/.envREDIS_PORT=6380//本地redis端口冲突RAGFLOW_IMA...
- 别再傻傻分不清!localhost、127.0.0.1、本机IP,原来大有讲究!
-
调试接口死活连不上?部署服务队友访问不了?八成是localhost、127.0.0.1、本机IP用混了!这三个看似都指向“自己”的东西,差之毫厘谬以千里。搞不清它们,轻则调试抓狂,重则服务裸奔。loc...
- 我把 Mac mini 托管到机房了:一套打败云服务器的终极方案
-
我把我积灰的Macmini托管到机房了,有图有真相。没想到吧?一台在家吃灰的苹果电脑,帮我省了大钱!对,就是控制了自己的服务器,省了租用云服务器的钱,重要数据还全捏在自己手里,这感觉真爽。你可...
你 发表评论:
欢迎- 一周热门
-
-
Redis客户端 Jedis 与 Lettuce
-
高并发架构系列:Redis并发竞争key的解决方案详解
-
redis如何防止并发(redis如何防止高并发)
-
Java SE Development Kit 8u441下载地址【windows版本】
-
redis安装与调优部署文档(WinServer)
-
开源推荐:如何实现的一个高性能 Redis 服务器
-
Redis 入门 - 安装最全讲解(Windows、Linux、Docker)
-
一文带你了解 Redis 的发布与订阅的底层原理
-
Redis如何应对并发访问(redis控制并发量)
-
Oracle如何创建用户,表空间(oracle19c创建表空间用户)
-
- 最近发表
- 标签列表
-
- oracle位图索引 (74)
- oracle批量插入数据 (65)
- oracle事务隔离级别 (59)
- oracle主从同步 (56)
- oracle 乐观锁 (53)
- redis 命令 (83)
- php redis (97)
- redis 存储 (67)
- redis 锁 (74)
- 启动 redis (73)
- redis 时间 (60)
- redis 删除 (69)
- redis内存 (64)
- redis并发 (53)
- redis 主从 (71)
- redis同步 (53)
- redis结构 (53)
- redis 订阅 (54)
- redis 登录 (62)
- redis 面试 (58)
- redis问题 (54)
- 阿里 redis (67)
- redis的缓存 (57)
- lua redis (59)
- redis 连接池 (64)