- 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的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
当我创建一个数据库时,我被要求选择默认排序规则,当我创建一个表时,我被要求选择排序规则。 utf8_general_ci 或...拉丁...?区分哪个是对的依据是什么? 最佳答案 A collatio
PHP不会检查单引号 '' 字符串中变量内插或(几乎)任何转义序列,所以采用单引号这种方式来定义字符串相当简单快捷。但是,双引号 "" 则不然,php会检查字符串中的变量或者转义
正则(regular),要使用正则表达式需要导入Python中的re(regular正则的缩写)模块。正则表达式是对字符串的处理,我们知道,字符串中有时候包含很多我们想要提取的信息,掌握这些处理字符
在开发过程中,有时需要对用户输入的类型做判断,最常见是在注册页面即用户名和密码,代码整理如下: 只能为中文 ?
]js正则表达式基本语法(精粹): http://www.zzvips.com/article/94068.html 许多语言,包括P
1、首先安装mongodb 1.下载地址:http://www.mongodb.org/downloads 2.解压缩到自己想要安装的目录,比如d:\mongodb 3.创建文件夹d:\mo
我更愿意在 R 中执行以下操作,但我愿意接受(易于学习的)其他解决方案。 我有多个(比如说 99 个)制表符分隔文件(我们称它们为 S1.txt 到 S99.txt)和表格,所有文件都具有完全相同的格
我制作了一个小程序,可以使用数学进行物理计算。 我有几个 if 语句,它们做同样的事情,但变量不同,但它们必须是它们,就好像 TextBox 是空的,int 将是 0。 例子如下: if (first
我正在构建需要扩展框的东西 - 这很好,我可以正常工作。然而,如果你看看这个FIDDLE你会看到它有点乱。我希望有一种方法可以扩展它们所在的盒子,这样它们就不会跳来跳去?那么盒子 3 的左侧会比右侧膨
我相当确定(在 MATLAB 中)应该有一个优雅的解决方案,但我现在想不起来。 我有一个包含 [classIndex, start, end] 的列表,我想将连续的类索引折叠成一个组,如下所示: 这个
维基百科将 XMPP 定义为: ...an open-standard communications protocol for message-oriented middleware based on
我的代码库已经进入了某种状态,希望能够摆脱它 repo 看起来有点像这样(A1、B1、C1 等显然是提交) A1 ---- A2 ---- A3 ---- A4 -
如何整理以下数据框 data.frame(a = c(1,2), values = c("[1.1, 1.2, 1.3]", "[2.1, 2.2]")) a values 1
所以我试图在 Haskell 中生成出租车号码列表。出租车号码是可以用两种不同方式写成两个不同立方体之和的数字 - 最小的是 1729 = 1^3 + 12^3 = 9^3 + 10^3 . 现在,我
我正在使用 roxygen2 来记录我正在开发的包的数据集。我知道你可以 use roxygen to document a dataset ,但是Shane's answer最终建议进行黑客攻击,虽
这个问题在这里已经有了答案: How can I combine two strings together in PHP? (19 个回答) 关闭 5 年前。 提前致歉,尽管我已经尝试并失败了几件不
我有一个大部分整洁的数据框,但有 2 列包含基准,而不是将基准合并为观察结果。我该如何整理,以便将“Facility_score”和“TTP”col_names 添加为每个独特的 FYQ 和 Metr
我有以下输入数据。每一行都是一个实验的结果: instance algo profit time x A 10 0.5 y A
我已经使用 PHP 和 MySQL 实现了搜索。目前我的表格整理是 "utf8_unicode_ci"。问题是,使用此排序规则 "ä"= "a" 是。如果我将排序规则更改为 "utf_bin" 一切正
所以我是 JS 和 Jquery 库的新手。我一直在玩弄一些东西,可以看到它非常不整洁,这就是我希望你们能帮助建议一种更好的方法来实现我想要实现的目标的地方。 目标: 要有多个复选框,其中一些如果被选
我是一名优秀的程序员,十分优秀!