当前位置:首页 > 面试题 > 正文内容

Spring 事务实现原理 (同一个类方法调用事务失效)

关中浪子3年前 (2021-07-26)面试题1695
【腾讯云】2核2G4M云服务器新老同享99元/年,续费同价
找梯子最重要的就是稳定,这个已经上线三年了,一直稳定没有被封过,赶紧下载备用吧!

Spring 声明式事务实现原理

起因

本人之前使用Spring事务时遇到两种场景。同一个class没有事务的A方法调用含有事务的B方法发现事务不生效,同一个class有事务的A方法调用含有事务的B方法(传播性为REQUIRES_NEW),独立事务也没有创建。

一切的原因就和 Spring 利用 AOP 代理实现声明式事务紧密关联了。


原因

我们知道,Spring的AOP实现方式有两种:1、Java代理方式;2、Cglib动态增强方式,这两种方式在Spring中是可以无缝自由切换的。Java代理方式的优点是不依赖第三方jar包,缺点是不能代理类,只能代理接口。Spring通过AopProxy接口,抽象了这两种实现,实现了一致的AOP方式:


现在看来,这种抽象同样带了一个缺陷,那就是抹杀了Cglib能够直接创建普通类的增强子类的能力,Spring相当于把Cglib动态生成的子类,当普通的代理类了,这也是为什么会创建两个对象的原因。下图显示了Spring的AOP代理类的实际调用过程:


因此,从上面的分析可以看出,methodB没有被AopProxy通知到,导致最终结果是:被Spring的AOP增强的类,在同一个类的内部方法调用时,其被调用方法上的增强通知将不起作用。


而这种结果,会造成什么影响呢:

1:内部调用时,被调用方法的事务声明将不起作用

2:换句话说,你在某个方法上声明它需要事务的时候,如果这个类还有其他开发者,你将不能保证这个方法真的会在事务环境中

3:再换句话说,Spring的事务传播策略在内部方法调用时将不起作用。不管你希望某个方法需要单独事务,是RequiresNew,还是要嵌套事务,要Nested,等等,统统不起作用。

4:不仅仅是事务通知,所有你自己利用Spring实现的AOP通知,都会受到同样限制。。。。


问题的原因已经找到,其实,我理想中的AOP实现,应该是下面这样:


只要一个Cglib增强对象就好,对于Java代理方式,我的选择是毫不犹豫的抛弃。


至于前面的事务问题,只要避开Spring目前的AOP实现上的限制,要么都声明要事务,要么分开成两个类,要么直接在方法里使用编程式事务,那么一切OK。



扫描二维码推送至手机访问。

版权声明:本文由码农翻生发布,如需转载请注明出处。

本文链接:https://lubojian.cn/post/37.html

分享给朋友:

相关文章

2023 java 基础面试题

Q1:Java内部类和子类之间有什么区别?答案:内部类是指在一个外部类的内部再定义一个类,内部类对外部类有访问权限,可以访问类中定义的所有变量和方法。子类是从父类(superclass)中继承的类,子类可以访问父类所有public和prot...

JAVA面试题附答案(长期更新)

JAVA基础基本类型分为数值型(byte,short,int,long,float,double),字符型,布尔型引用类型包含类,接口,数组String能被继承吗?为什么?不可以,因为String类有final修饰符,而final修饰的类是...

Java笔试题大全带答案,2023年精选解答

1. 下面关于java.lang.Exception类的说法正确的是()A 继承自Throwable B Serialable CD 不记得,反正不正确答案:A解析:Java异常的基类为java.lang.Throwable,java.la...

发表评论

访客

看不清,换一张

◎欢迎参与讨论,请在这里发表您的看法和观点。