- ubuntu12.04环境下使用kvm ioctl接口实现最简单的虚拟机
- Ubuntu 通过无线网络安装Ubuntu Server启动系统后连接无线网络的方法
- 在Ubuntu上搭建网桥的方法
- ubuntu 虚拟机上网方式及相关配置详解
CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.
这篇CFSDN的博客文章【面试】Spring事务面试考点吐血整理(建议珍藏)由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.
starting from a joke 。
问:把大象放冰箱里,分几步?
答:三步啊,第1、把冰箱门打开,第2、把大象放进去,第3、把冰箱门带上.
问:实现spring事务,分几步?
答:三步啊,第1、找出需要事务的方法,第2、把事务加进去,第3、执行事务.
you may find it's not a joke, it's serious.
try to find an entrance 。
当你面对一个完全不熟悉的事物时,一定要想办法找到一个突破口,然后逐步深入。那spring事物的突破口在哪里呢?很明显在@enabletransactionmanagement注解里,因为是它启用了事物功能.
请看下图:
发现注解还引入了一个类transactionmanagementconfigurationselector.
再来看这个类,如下图:
发现如果采用代理的方式时,又引入了一个类proxytransactionmanagementconfiguration.
接着看这个类(重点来了),如下图:
发现这个类往容器中注册了3个bean,第一个是beanfactorytransactionattributesourceadvisor。它以advisor结尾说明它是spring aop范畴里的东西.
在aop里,advisor = pointcut + advice,pointcut是切入点,表示要拦截的方法,advice是增强,表示要加进去的事物功能.
再看看另外两个注册的bean,就是和这两个相关的。其中transactioninterceptor就是一个advice,因为它实现了advice接口,包含了把事物加进去的逻辑.
transactionattributesource虽然不是一个pointcut,但是它被pointcut所用,用于检测一个类的方法上是否有@transactional注解,来确定该方法是否需要事物增强.
从下图中也可以看出这一点:
可以看到这个bean通过下面的set方法被设置进去,然后又用在了pointcut的类里了.
整体来看,此部分的结构和功能划分还是非常清晰的。下面来逐一研究.
aop切点 。
transactionattributesourcepointcut类以pointcut结尾,说明它是一个切入点,就是标识要被拦截的方法。类名的前缀部分表明了这个切入点的实现原理.
看下这个前缀是transactionattributesource,它以source结尾,说明它是一个源(即源泉,有向外提供东西的意思)。它的前缀是transactionattribute,即事务属性.
由此可见,这个源可以向外提供事务属性,其实就是判断一个类的方法上是否标有@transactional注解,如果有的话还可以获取这个注解的属性(即事务属性).
整体来说就是,pointcut拦截住了方法,然后使用这个“源”去方法和类上获取事务属性,如果能获取到,说明此方法需要参与事务,则进行事务增强,反之则不增强.
下面这张图可以证明我们的想法:
可以看出matches方法的两个参数就是一个方法(method)和一个类(class<?>)。最后从方法和类上获取事务属性,再进行是否为null判断.
现在这个“源”还是个黑盒子,下面来揭开它的面纱。它的实现类是annotationtransactionattributesource,以annotation开头,说明是基于注解实现的.
下面图是它的源码的一部分:
第一个方法从类上找事务属性,第二个方法从方法上找事务属性,它俩都调用了第三个方法来实现.
ps:我们都知道,方法上的注解优先级高于类上的,是因为找注解时先找方法上的,找不到时再去类上找。所以方法上的优先级高。此部分代码逻辑在父类里写着呢,这里不再展示了.
第三个方法使用多个事务注解解析器(transactionannotationparser)去解析注解,为啥是多个解析器呢?因为事务注解不仅spring提供了,java后来也提供了,就是javax.transaction.transactional.
spring对自己注解的解析器实现类是springtransactionannotationparser,如下图:
可以看出使用工具类来读取注解@transactional的属性,然后逐个解析出属性值并进行类型转换,接着把这些属性封装到一个类里,这个类其实就是事务属性,即transactionattribute.
这个事务属性继承了事务定义接口,事务定义接口我们应该都很熟悉,如下图:
这也证明了以前文章里说过的话,@transactional注解的作用有两个,一是表明要参与事务,二是表明如何参与事务,这些注解属性就是来规定如何参与的.
这个事务属性transactionattribute是个接口,它的实现类在这里就不再详说了.
aop增强 。
advice就是aop中的增强,transactioninterceptor实现了advice接口,所以它就是事务增强.
先来看下该接口,如下图:
发现它只是一个空的标记接口。而且它的包名是org.aopalliance,是一个aop联盟组织,它制定的aop规范.
先来了解下aop领域的一些相关内容,pointcut是切入点,表示要拦截的方法。它是一个静态的概念,即程序不运行时它也是存在的.
那么在真正运行时,已经拦截住了,此时该怎么表示这个情况呢?是用joinpoint来表示的,所以joinpoint是一个运行时的概念,只有在运行时才存在.
请看joinpoint接口,如下图:
第一个方法proceed()是“继续”的意思,调用它表示去执行被拦截住的方法本身,返回方法本身的返回值.
第二个方法getthis()是获取this对象,即方法运行时所在的目标对象。如果是静态方法,则为null,因为静态方法是属于类本身的,运行时不需要对象.
第三个方法getstaticpart(),其实就表示了被拦截住的方法,即就是一个method。method其实算是“元数据”,是属于类型本身的,也有“静态”的意思.
再看一个接口,invocation,它继承了joinpoint,如下图:
方法getarguments()就表示运行时传递给被拦截住方法的参数.
再看一个接口,methodinvocation,它继承了invocation,如下图:
方法getmethod()返回一个method,它就是当前正在执行的方法,是对本拦截方法的一个友好实现,返回相同的结果.
可见methodinvocation接口已经包含了一个方法调用的全量信息,方法,参数,目标对象。这其实就是运行时被拦截住的东西.
再看下面这个接口,methodinterceptor,方法拦截器,如下图:
它只有一个方法invoke,方法参数就是上面介绍的methodinvocation。所以拦截器可以使用这个参数来对目标方法进行调用,当然在调用前/后可以加入自己的逻辑.
transactioninterceptor类就实现了这个接口,因此可以在对目标方法的调用前后插入事务逻辑代码来进行事务增强.
下面是事务拦截器对该方法的实现,如下图:
它调用的invokewithintransaction方法是在父类里的,看下图:
这个图里做的事情较多,逐个来看:
前两行获取事务属性“源”,再用这个“源”来获取事务属性。咦,有点奇怪,上面不是已经获取过了吗?是的,上面是在pointcut里获取的,那只是用于判断那个方法是否要被拦截而已。这里获取的属性才是真正用于事务的.
第三行是根据事务属性,来确定出一个事务管理器来.
接下来是使用事务管理器打开事务.
接下来是对被拦截住的目标方法的调用执行,当然要try/catch住这个执行.
如果抛出了异常,则进行和异常相关的事务处理,然后将这个异常继续向上抛出.
如果没有抛出异常,则进行事务提交.
最后的else分支是对编程式事务的调用,事务的打开/提交/回滚是开发人员自己写代码控制,所以就不需要事务管理器操心了.
下面请看和异常相关的事务处理,如下图:
判断异常类型是否需要回滚,需要的话就回滚事务,不需要的话就继续提交事务.
这里的整体结构和逻辑流程也是比较清晰的,那是因为一方面得益于aop领域的概念,另一方面是事务管理器屏蔽了事务的所有复杂性.
ps:事务管理器的内容其实还是挺复杂的,下篇文章再详细解说.
好了,以上是小编给大家介绍的spring事务面试整理,希望对大家有所帮助,如果大家有任何疑问欢迎给我留言,小编会及时回复大家的! 。
原文链接:https://www.cnblogs.com/lixinjie/archive/2019/04/16/a-enough-source-read-of-spring-tx-for-interview.html 。
最后此篇关于【面试】Spring事务面试考点吐血整理(建议珍藏)的文章就讲到这里了,如果你想了解更多关于【面试】Spring事务面试考点吐血整理(建议珍藏)的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我正在使用 PostgREST 将数据库实体暴露给使用这些实体的 Springboot 应用。 我的数据库中有两个实体,分别是 Person 和 City。 我想同时保存 Person 实体和 Cit
1、事务的定义 Redis的事务提供了一种“将多个命令打包, 然后一次性、按顺序地执行”的机制。 redis事务的主要作用就是串联多个命令防止别的命令插队。 但是,事务并不具有传统
SQLite 事务(Transaction) 事务(Transaction)是一个对数据库执行工作单元。事务(Transaction)是以逻辑顺序完成的工作单位或序列,可以是由用户手动操作完成,也可
事务是顺序组操作。 它们作为单个单元运行,并且直到组中的所有操作都成功执行时才终止。 组中的单个故障会导致整个事务失败,并导致对数据库没有影响。 事务符合ACID(原子性,一致性,隔离和耐久性)
我希望将 SqlKata 用于一个项目。但是,项目标准的一部分是查询应该能够作为事务执行。有没有一种方法可以使用 MSSQL 事务执行一个查询或多个查询? 非常感谢。 最佳答案 SQLKata 使用
我只是以多线程方式测试 PetaPoco 事务... 我有一个简单的测试用例: -- 简单的值对象称之为 MediaDevice -- 插入一条记录,更新1000次 void TransactionT
我正在尝试从 Excel VBA 向 SQL 中插入一些数据。 SQL 命令是在 VBA 脚本的过程中构建的,包括使用一些 SQL 变量。 我试图了解事务在 VBA 中是如何工作的,以及它们是否可以处
情况如下: 一个大型生产客户端/服务器系统,其中一个中央数据库表具有某个列,该列的默认值是 NULL,但现在默认值是 0。但是在该更改之前创建的所有行当然仍然具有 null 值,这会在该系统中生成许多
数据库事务是一个熟悉的概念。 try { ... .. updateDB() .. ... commit(); } catch error { rollback(); }
我想了解使用传播支持进行 Spring 交易的用途。 java 文档提到如果具有 @Transactional(propagation = Propagation.SUPPORTS) 的方法从支持该事
我需要获取 hibernate 的事务 ID。对于每笔交易,此 ID 必须是唯一的。我尝试使用 session.getTransaction().hashCode(),但我相信这个值不是唯一的。 最佳
我从 firebase 收到以下消息:runTransactionBlock:启用持久性时检测到的使用情况。请注意,事务不会在应用重新启动后保留。 那么应用程序重新启动后到底会发生什么?由于主数据库的
我需要在 jdbc 中执行选择、更新、插入查询的序列。 这是我的代码: public String editRequest(){ connection = DatabaseUtil.getServi
Java 是否提供了一种智能“聚合”事务的方法?如果我有多个异构数据存储库,我想保持同步(即用于数据的 Postgres、用于图表的 Neo4j 以及用于索引的 Lucene),是否有一个范例仅允许
我对标题中的主题有几个问题。首先,假设我们使用 JDBC,并且有 2 个事务 T1 和 T2。在 T1 中,我们在一个特定的行上执行 select 语句。然后我们对该行执行更新。在事务 T2 中,我们
我有一个 Python CGI 处理支付交易。当用户提交表单时,CGI 被调用。提交后,CGI 需要一段时间才能执行信用卡交易。在此期间,用户可能会按下 ESC 或刷新按钮。这样做不会“杀死”CGI,
我有一个代码,类似这样 def many_objects_saving(list_of_objects): for some_object in list_of_objects:
我有一个包含 100,000 条记录的表。我正在考虑使用事务来更新数据。将有一个查询将一列更新为零,并且大约有 5000 个更新,每个更新将更新一条记录。 这些大型事务对内存有何影响?事务运行时选择数
有没有办法在一个命令中执行 SQL 事务?例如 mysql_query(" START TRANSACTION; INSERT INTO table1 ....etc; INSERT INTO tab
真心希望能帮到你! 我使用以下函数在 PHP/MySql 应用程序中发送消息: public function sendMail($sender_id, $recipient_id, $subject
我是一名优秀的程序员,十分优秀!