当目标类实现了接口 则采用jdk动态代理
当目标类没有实现接口则采用cglib动态代理
public class a implements A 这种是实现接口的方式, spring采用jdk动态代理实现事务管理
public class a 这种事没有实现接口的方式, 也就是说service只有一个实现类,这个实现类没有继承接口,则spring采用cglib动态代理的方式实现事务管理
springboot 声明式事务管理基于AOP, 在执行被@Transation标注的方法时,拦截该方法,在该方法执行前开启事务。 当该方法执行后,提交事务。
spring源码中rollBackFor指定的异常类是 runTimeExecption. 可以自己指定回滚对应的异常
思考: 在一个类中, 有A B两个方法。 A方法添加了事务注解, B方法没有添加事务注解。 在B方法中调用A时,A还有事务吗?
答:此时A中没有事务。 因为:spring是通过代理类对事务进行操作的。 A方法有事务, 单独调用A方法时, spring对于添加事务的方法,是通过创建一个和普通类 类似的
代理类,通过代理类做aop来对方法前后创建事务和提交事务。 对于没有添加事务的B方法, spring直接调用普通类,不创建代理类 。 所以在B中调用A时, 由于B没有开启
事务,spring调用的是B的普通类而不是代理类,无法创建事务和提交事务。 所以B中调用的A失效。
能不能支持事务,要看被调用方法的类是不是代理类。 是代理类,调用方法就支持事务。
事务只对public修饰的方法起作用。
@Transaction默认检测异常为RuntimeException及其子类 如果有其他异常需要回滚事务的需要自己手动配置,例如:@Transactional(rollbackFor = Exception.class)
确保异常没有被try-catch{},catch以后也不会回滚
数据库层面,数据库使用的存储引擎是否支持事务?默认情况下MySQL数据库使用的是Innodb存储引擎(5.5版本之后),它是支持事务的,但是如果你的表特地修改了存储引擎,例如,你通过下面的语句修改了表使用的存储引擎为MyISAM,而MyISAM又是不支持事务的;
Springboot项目默认已经支持事务,不用配置;其他类型项目需要在xml中配置是否开启事务
如果在同一个类中,一个非@Transaction的方法调用有@Transaction的方法不会生效,因为代理问题
一个非@Transaction的方法调用有@Transaction的方法不会生效。如果是在同一个类中的方法调用,则不会被方法拦截器拦截到,因此事务不会起作用,必须将方法放入另外一个类中,并且该类通过Spring注入。
Spring 采用动态代理(AOP)实现对Bean的管理和切片,它为我们的每个class生成一个代理对象,只有在代理对象之间进行调用时,可以触发切面逻辑。而在同一个类中,方法B调用A,调用的事元对象的方法,而不是通过代理对象,所以spring无法切到这次调用,也就是无法通过注解保证事务性。
不讨论内部类的情况下, 普通类不能被private 和 protected 修饰。
如果try-catch后用finally 强制返回值,则不会回滚
事务的传递问题:
A和B两类,在A中调用B时:
如果serviceA.methodA已经起了事务,这是调用ServiceB.methodB, ServiceB.methodB看到自己已经运行在ServiceA.methodA的事务内部,就不再启新的事务
这是直接共用外部事务,所以此时ServiceA.methodA或者ServiceB.methodB无论哪个发生异常,methodA 和 methodB作为一个整体都将一起回滚。
如果serviceA.methodA没有事务,serviceB.methodB就会为自己新建一个事务,此时在serviceA.methodA中是没有事务管理的,serviceB.methodB内的任何地方
出现异常,ServiceB.methodB将会被回滚,但是不会引起serviceA.methodA的回滚。
Spring 动态代理与事务管理详解
797

被折叠的 条评论
为什么被折叠?



