@Transactional解析

不生效的情况

  • 首先@Transactional注解在私有方法上不生效
    原因是生成的代理类访问不到私有方法,所以不会生效
  • 如果Spring项目没有开启事务,就是在某个配置类上增加@EnableTransactionManagement开启事务管理的注解,那么也会失效。或者在Spring容器中手动创建事务管理器这个Bean
    SpringBoot在@SpringBootApplication注解中开启了事务管理,它的实现原理是去读取spring.factories文件,它会自动加载一些启动类,其中就包含了事务管理启动类
  • 抛出的异常不是Error与RuntimeException,而是非运行时异常
    默认回滚 Error与 RuntimeException运行时异常
  • 异常被内部捕获了
  • A方法内部调用了B方法,而且B方法也加了事务注解,这种情况也是不会回滚的。
  • 数据库引擎不支持事务,目前常见的InnoDB是支持的

原理分析

Spring的事务管理类实际上是AOP的应用,启动类Spring的事务,相当于关闭了事务的自动提交。

在使用了@Transactional注解的类上,实际上为这个类创建的代理。业务代码如果正常,在方法执行完毕后,向数据库提交事务。如果出错,则再根据注解上的配置决定是不是要回滚。

public abstract class TransactionAspectSupport ...{

	protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass,
			final InvocationCallback invocation) throws Throwable {
		....
		try {
			// 这里最终会调用到目标方法
			retVal = invocation.proceedWithInvocation();
		} catch (Throwable ex) {
			// 目标方法抛出了异常,根据@Transactional注解属性配置决定是否需要回滚事务
			completeTransactionAfterThrowing(txInfo, ex);
			throw ex;
		}
		...
        //目标方法正常执行完成,提交事务
		commitTransactionAfterReturning(txInfo);
		....
}
posted @ 2022-07-17 12:12  小大宇  阅读(85)  评论(0编辑  收藏  举报