事务主要有四大特性:原子性,一致性,隔离性和持久性。对于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则封装了需要织入的切面逻辑。如下是这三个部分的简要关系图:
对于Spring事务,其既然是使用Spring Aop实现的,那么也同样会有这三个成员,Advisor对应BeanFactoryTransactionAttributeSourceAdvisor
类,而Advice对应TransactionInterceptor
类,Pointcut则对应TransactionAttributeSourcePointcut
类,同样这三个类的关系如下:
这三个类的作用分别是:
- 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事务用法示例与实现原理
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。