百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术教程 > 正文

从0到1深入解读Spring AOP、 IOC、 事务的属性,传播行为,隔离级别

mhr18 2025-06-15 17:38 5 浏览 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 是最高的事务隔离级别,同时代价也花费最高,性能很低,一般很少使用,在该

级别下,事务顺序执行,不仅可以避免脏读、不可重复读,还避免了幻像读。

相关推荐

SQL入门知识篇(sql入门新手教程视频)

一、什么是数据库?什么是SQL?1、数据库:存放数据,可以很多人一起使用2、关系数据库:多张表+各表之间的关系3、一张表需要包含列、列名、行4、主键:一列(或一组列),其值能够唯一区分表中的每个行。5...

postgresql实现跨库查询-dblink的妙用

技术导语:用惯了oracle的dblink,转战postgresql,会一时摸不着头脑。本期就重点详细讲解postgresql如何安装dblink模块及如何使用dblink实现跨库查询。安装cont...

Oracle VM VirtualBox虚拟机软件(oracle vm virtualbox win10)

OracleVMVirtualBox是一款完全免费的虚拟机软件,下载银行有提供下载,软件支持安装windows、linux等多个操作系统,让用户可以在一台设备上实现多个操作系统的操作。同时软件有着...

开源 SPL 轻松应对 T+0(开源srs)

T+0问题T+0查询是指实时数据查询,数据查询统计时将涉及到最新产生的数据。在数据量不大时,T+0很容易完成,直接基于生产数据库查询就可以了。但是,当数据量积累到一定程度时,在生产库中进行大数据...

中小企业佳选正睿ZI1TS4-4536服务器评测

随着科技的不断发展,各行各业对于数据使用越加频繁,同时针对服务器的选择方面也就越来越多样化和细分化。那么对于我们用户来说,如何选择符合自身业务需求和最优性价比的产品呢?笔者将通过刚刚购买的这台服务器的...

MFC转QT:Qt基础知识(mfc和qt的区别)

1.Qt框架概述Qt的历史和版本Qt是一个跨平台的C++应用程序开发框架,由挪威公司Trolltech(现为QtCompany)于1991年创建。Qt的发展历程:1991年:Qt项目启动1995年...

数据库,QSqlTableModel(数据库有哪些)

QMYSQL——mysqlQSQLITE——sqliteQOICQ——orcale所需头文件.pro增加sql#include<QSqlDatabase>#include<Q...

python通过oledb连接dbf数据库(python连接jdbc)

起因:因为工作需要,需要读取dbf文件和系统数据中数据进行校对,因为知道dbf文件可以用sql查询,所以想能不能像mysql/oracle那样连接,再调用执行sql方法,通过一系列百度,尝试,最终通过...

Excel常用技能分享与探讨(5-宏与VBA简介 VBA与数据库)

在VBA(VisualBasicforApplications)中使用数据库(如Access、SQLServer、MySQL等)具有以下优点,适用于需要高效数据管理和复杂业务逻辑的场景:1....

Excel常用技能分享与探讨(5-宏与VBA简介 VBA与数据库-二)

以下是常见数据库软件的详细配置步骤,涵盖安装、驱动配置、服务启动及基本设置,确保VBA能够顺利连接:一、MicrosoftAccess适用场景:小型本地数据库,无需独立服务。配置步骤:安装Acces...

Windows Docker 安装(docker安装windows容器)

Docker并非是一个通用的容器工具,它依赖于已存在并运行的Linux内核环境。Docker实质上是在已经运行的Linux下制造了一个隔离的文件环境,因此它执行的效率几乎等同于所部署的L...

Windows下安装Ubuntu虚拟机方法(windows下安装ubuntu20)

在Windows下安装Ubuntu虚拟机。选择使OracleVMVirtualBox安装Ubuntu虚拟机。1.下载和安装OracleVMVirtualBox:访问OracleVMVir...

java入门教程1 - 安装和配置(win和linux)

windows安装和配置安装javahttps://www.oracle.com/java/technologies/javase/javase-jdk8-downloads.html目前大部分项目的...

Centos7 安装Tomcat8服务及配置jdk1.8教程

1、下载jdk1.8压缩包下载地址:https://www.oracle.com/java/technologies/javase/javase8-archive-downloads.htmltom...

全网最完整的免费java教程讲义(一)——java配置和安装

一,安装Java1)安装JDK要学习和使用java,首先需要安装JDK(JavaDevelopemntKit),相当于java安装包。Java的下载页在甲骨文官网上:https://www.or...

取消回复欢迎 发表评论: