事务主要有四大特性:原子性,一致性,隔离性和持久性。对于Spring事务,其最终还是在数据库层面实现的,而Spring只是以一种比较优雅的方式对其进行封装支持。

spring常用的事务管理方式有aspectj与基于注解这两种,使用aspectj通过在xml配置文件中指定事务的传播级别,隔离级别,切入点(需要增强的方法),切面等。配置较繁琐但可以做到项目不与框架耦合;基于注解只需要在进行事务管理的方法上使用@Transactional,然后在xml文件中注明<tx:annotation-driven/>就可以开启事务了。当然两种事务开启的入口都是通过<tx:annotation-driven/>实现的。

下面这里记录下使用@Transactional注解的方式:
tx:annotation-driven才是Spring事务的驱动,spring会在TxNamespaceHandler注册相应的parser,然后在AnnotationDrivenBeanDefinitionParser中对annotation-driven进行处理,处理后会得到一个名为BeanFactoryTransactionAttributeSourceAdvisor类型的bean,并会将这个bean注册到BeanFactory中,其实际为Advisor类型,这也是Spring事务能够通过Aop实现事务的根本原因。

Aop在进行解析的时候,最终会生成一个Adivsor对象,这个Advisor对象中封装了切面织入所需要的所有信息,其中就包括最重要的两个部分就是Pointcut和Adivce属性。这里Pointcut用于判断目标bean是否需要织入当前切面逻辑;Advice则封装了需要织入的切面逻辑。如下是这三个部分的简要关系图:
image.png
对于Spring事务,其既然是使用Spring Aop实现的,那么也同样会有这三个成员,Advisor对应BeanFactoryTransactionAttributeSourceAdvisor类,而Advice对应TransactionInterceptor类,Pointcut则对应TransactionAttributeSourcePointcut类,同样这三个类的关系如下:
image.png
这三个类的作用分别是:

  • BeanFactoryTransactionAttributeSourceAdvisor:封装了实现事务所需的所有属性,包括Pointcut,Advice,TransactionManager以及一些其他的在Transactional注解中声明的属性;
  • TransactionAttributeSourcePointcut:用于判断哪些bean需要织入当前的事务逻辑。这里可想而知,其判断的基本逻辑就是判断其方法或类声明上有没有使用@Transactional注解,如果使用了就是需要织入事务逻辑的bean;
  • TransactionInterceptor:这个bean本质上是一个Advice,其封装了当前需要织入目标bean的切面逻辑,也就是Spring事务是如果借助于数据库事务来实现对目标方法的环绕的。

最后,spring进行事务提交的方法是:

org.springframework.transaction.support.AbstractPlatformTransactionManager#processCommit

提交的时候有多种选择,其中就有jdbc(其它的有JMS,Hibernate,JPA等)。

最后说明下,Spring AOP使用了两种代理机制,一种是基于JDK的动态代理(默认),另一种是基于CGLib的动态代理。

spring事务超时不起作用的原因

事务不回滚的场景

参考的文章:Spring事务用法示例与实现原理

Spring事务相关文章


步履不停
38 声望14 粉丝

好走的都是下坡路