目录
Springboot 数据库事务
数据库事务
( transaction
)是访问并可能操作各种数据项的一个数据库操作序列,这些操作要么全部执行,要么全部不执行,是一个不可分割的工作单位。事务由事务开始与事务结束之间执行的全部数据库操作组成。
在开始Springboot教程之前先引入几个概念以便后续的讲解:
ACID
ACID 是指数据库管理系统(DBMS)在写入或更新资料的过程中,为保证事务(transaction)是正确可靠的,所必须具备的四个特性:原子性
(atomicity,或称不可分割性)、一致性
(consistency)、隔离性
(isolation,又称独立性)、持久性
(durability)。
事务的隔离级别
-
事务的隔离级别:
第一种隔离级别:Read uncommitted(读未提交)
如果一个事务已经开始写数据,则另外一个事务不允许同时进行写操作,但允许其他事务读此行数据,该隔离级别可以通过“排他写锁”,但是不排斥读线程实现。这样就避免了更新丢失,却可能出现脏读,也就是说事务B读取到了事务A未提交的数据。
解决了更新丢失,但还是可能会出现脏读 -
第二种隔离级别:Read committed(读提交)
如果是一个读事务(线程),则允许其他事务读写,如果是写事务将会禁止其他事务访问该行数据,该隔离级别避免了脏读,但是可能出现不可重复读。事务A事先读取了数据,事务B紧接着更新了数据,并提交了事务,而事务A再次读取该数据时,数据已经发生了改变。
解决了更新丢失和脏读问题 -
第三种隔离级别:Repeatable read(可重复读取)
可重复读取是指在一个事务内,多次读同一个数据,在这个事务还没结束时,其他事务不能访问该数据(包括了读写),这样就可以在同一个事务内两次读到的数据是一样的,因此称为是可重复读隔离级别,读取数据的事务将会禁止写事务(但允许读事务),写事务则禁止任何其他事务(包括了读写),这样避免了不可重复读和脏读,但是有时可能会出现幻读。(读取数据的事务)可以通过“共享读镜”和“排他写锁”实现。
解决了更新丢失、脏读、不可重复读、但是还会出现幻读
MySQL默认使用的隔离级别 -
第四种隔离级别:Serializable(可序化)
提供严格的事务隔离,它要求事务序列化执行,事务只能一个接着一个地执行,但不能并发执行,如果仅仅通过“行级锁”是无法实现序列化的,必须通过其他机制保证新插入的数据不会被执行查询操作的事务访问到。序列化是最高的事务隔离级别,同时代价也是最高的,性能很低,一般很少使用,在该级别下,事务顺序执行,
不仅可以避免脏读、不可重复读,还避免了幻读,但使用此隔离界别性能会比较差。
Springboot事务和数据库事务的区别,Springboot的时候是Springboot自己实现的一套事务控制而不是直接操控数据库事务,假如说在集群情况下两台并发同时操作一条数据,这个时候还是要依赖于数据库事务进行处理。
使用教程
maven 引入
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>${springboot.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>${springboot.version}</version>
</dependency>
<!-- mysql or oracle driver package -->
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.26</version>
</dependency>
简单使用
在Springboot中使用数据库事务非常简单,使用@Transactional(propagation = Propagation.REQUIRED)
注解就可以快速使用事务了。
示例:
@Autowired
JdbcTemplate jdbcTemplate;
@Transactional
public void testTransaction() {
// 伪代码
invokeBefore();
jdbcTemplate.update("update user set name = 'test-name-002' where id = 1;"); // ①
invokeAfter();
}
如果方法invokeBefore()
和 invokeAfter
发生报错则更新user的操作就不会被提交。那考虑下过其他其他Bean
调用完testTransaction
之后报错了会不会回滚事务呢?答案是不会(下面会讲为什么)。
事务传递
事务传播行为的7种类型:
如果@Transactional
不指定事务传递行为默认是PROPAGATION_REQUIRED
,我们看下@Transactional这个注解有哪些属性:
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Transactional {
/**
* Alias for {@link #transactionManager}.
* @see #transactionManager
*/
@AliasFor("transactionManager")
String value() default "";
/**
* 指定事务管理器,Springboot中可以创建多个事务管理器,在注解中可以进行指定
*/
@AliasFor("value")
String transactionManager() default "";
/**
* 默认是REQUIRED,每个方法前或者类上都可以指定事务传递级别
*/
Propagation propagation() default Propagation.REQUIRED;
/**
* 事务隔离级别
*/
Isolation isolation() default Isolation.DEFAULT;
/**
* The timeout for this transaction (in seconds).
* <p>Defaults to the default timeout of the underlying transaction system.
* <p>Exclusively designed for use with {@link Propagation#REQUIRED} or
* {@link Propagation#REQUIRES_NEW} since it only applies to newly started
* transactions.
* @see org.springframework.transaction.interceptor.TransactionAttribute#getTimeout()
*/
int timeout() default TransactionDefinition.TIMEOUT_DEFAULT;
/**
* 是否只读
*/
boolean readOnly() default false;
/**
* 遇到什么错误类型会进行回滚操作,如果不是指定错误类型
*/
Class<? extends Throwable>[] rollbackFor() default {};
String[] rollbackForClassName() default {};
Class<? extends Throwable>[] noRollbackFor() default {};
String[] noRollbackForClassName() default {};
}
可以看到Springboot默认的事务传递级别是Required,回到上面问题,为什么其他Bean
调用完testTransaction
之后报错了不会回滚事务。因为Required的隔离级别是当前方法必须在事务中运行,如果当前线程中没有事务,则开启一个新的事务;如果当前线程中已经存在事务,则方法将会在该事务中运行。明显已经存在事务了,别的bean在调用完testTransaction
之后testTransaction
的事务就已经提交了,再抛出异常不会影响到testTransaction
。如果想让别的bean和被调用的testTransaction
都在同一个事务下,可以把@Transactional加到最上层即可。
Isolation
事务的隔离级别
public enum Isolation {
/**
* Use the default isolation level of the underlying datastore.
* All other levels correspond to the JDBC isolation levels.
* @see java.sql.Connection
* 根据默认的JDBC 驱动取事务的隔离级别 MySQL 默认就是可重复读
*/
DEFAULT(TransactionDefinition.ISOLATION_DEFAULT),
/**
* A constant indicating that dirty reads, non-repeatable reads and phantom reads
* can occur. This level allows a row changed by one transaction to be read by
* another transaction before any changes in that row have been committed
* (a "dirty read"). If any of the changes are rolled back, the second
* transaction will have retrieved an invalid row.
* @see java.sql.Connection#TRANSACTION_READ_UNCOMMITTED
*/
READ_UNCOMMITTED(TransactionDefinition.ISOLATION_READ_UNCOMMITTED),
/**
* A constant indicating that dirty reads are prevented; non-repeatable reads
* and phantom reads can occur. This level only prohibits a transaction
* from reading a row with uncommitted changes in it.
* @see java.sql.Connection#TRANSACTION_READ_COMMITTED
*/
READ_COMMITTED(TransactionDefinition.ISOLATION_READ_COMMITTED),
/**
* A constant indicating that dirty reads and non-repeatable reads are
* prevented; phantom reads can occur. This level prohibits a transaction
* from reading a row with uncommitted changes in it, and it also prohibits
* the situation where one transaction reads a row, a second transaction
* alters the row, and the first transaction rereads the row, getting
* different values the second time (a "non-repeatable read").
* @see java.sql.Connection#TRANSACTION_REPEATABLE_READ
*/
REPEATABLE_READ(TransactionDefinition.ISOLATION_REPEATABLE_READ),
/**
* A constant indicating that dirty reads, non-repeatable reads and phantom
* reads are prevented. This level includes the prohibitions in
* {@code ISOLATION_REPEATABLE_READ} and further prohibits the situation
* where one transaction reads all rows that satisfy a {@code WHERE}
* condition, a second transaction inserts a row that satisfies that
* {@code WHERE} condition, and the first transaction rereads for the
* same condition, retrieving the additional "phantom" row in the second read.
* @see java.sql.Connection#TRANSACTION_SERIALIZABLE
*/
SERIALIZABLE(TransactionDefinition.ISOLATION_SERIALIZABLE);
private final int value;
Isolation(int value) {
this.value = value;
}
public int value() {
return this.value;
}
}
配置TransactionManager
默认的TransactionManager
一般情况下我们想起用TransactionManager都会在configuration中启用注解@EnableTransactionManagement
,其实我们不启用这个注解Springboot也会默认启用事务。
在springboot-autoconfig中会自动注入TransactionManager,我们看下TransactionAutoConfiguration
代码:
@Configuration(
proxyBeanMethods = false
)
// 依赖Spring-tx包
@ConditionalOnClass({PlatformTransactionManager.class})
@AutoConfigureAfter({JtaAutoConfiguration.class, HibernateJpaAutoConfiguration.class, DataSourceTransactionManagerAutoConfiguration.class, Neo4jDataAutoConfiguration.class})
@EnableConfigurationProperties({TransactionProperties.class})
public class TransactionAutoConfiguration {
public TransactionAutoConfiguration() {
}
@Bean
@ConditionalOnMissingBean
public TransactionManagerCustomizers platformTransactionManagerCustomizers(ObjectProvider<PlatformTransactionManagerCustomizer<?>> customizers) {
return new TransactionManagerCustomizers((Collection)customizers.orderedStream().collect(Collectors.toList()));
}
@Bean
@ConditionalOnMissingBean
@ConditionalOnSingleCandidate(ReactiveTransactionManager.class)
public TransactionalOperator transactionalOperator(ReactiveTransactionManager transactionManager) {
return TransactionalOperator.create(transactionManager);
}
@Configuration(
proxyBeanMethods = false
)
@ConditionalOnBean({TransactionManager.class})
@ConditionalOnMissingBean({AbstractTransactionManagementConfiguration.class}) // 如果Springboot中没有事务管理器则会自动配置注册一个
public static class EnableTransactionManagementConfiguration {
public EnableTransactionManagementConfiguration() {
}
@Configuration(
proxyBeanMethods = false
)
@EnableTransactionManagement(
proxyTargetClass = true
)
@ConditionalOnProperty(
prefix = "spring.aop",
name = {"proxy-target-class"},
havingValue = "true",
matchIfMissing = true
)
public static class CglibAutoProxyConfiguration {
public CglibAutoProxyConfiguration() {
}
}
@Configuration(
proxyBeanMethods = false
)
@EnableTransactionManagement(
proxyTargetClass = false
)
// 启用事务注解,默认为PROXY模式,JDK动态代理实现增强事务
@ConditionalOnProperty(
prefix = "spring.aop",
name = {"proxy-target-class"},
havingValue = "false",
matchIfMissing = false
)
public static class JdkDynamicAutoProxyConfiguration {
public JdkDynamicAutoProxyConfiguration() {
}
}
}
@Configuration(
proxyBeanMethods = false
)
@ConditionalOnSingleCandidate(PlatformTransactionManager.class)
public static class TransactionTemplateConfiguration {
public TransactionTemplateConfiguration() {
}
@Bean
@ConditionalOnMissingBean({TransactionOperations.class})
public TransactionTemplate transactionTemplate(PlatformTransactionManager transactionManager) {
return new TransactionTemplate(transactionManager);
}
}
}
手动配置事务拦截器
@EnableTransactionManagement
@Configuration
public class GlobalTransactionConfig implements ApplicationListener<ApplicationStartedEvent> {
//写事务的超时时间为10秒
private static final int TX_METHOD_TIMEOUT = 10;
//restful包下所有service包或者service的子包的任意类的任意方法
private static final String AOP_POINTCUT_EXPRESSION = "execution (* com.allens.export.service.*.*(..))";
@Autowired
private TransactionManager transactionManager;
@Bean
public TransactionInterceptor txAdvice() {
/**
* 这里配置只读事务
*/
RuleBasedTransactionAttribute readOnlyTx = new RuleBasedTransactionAttribute();
readOnlyTx.setReadOnly(true);
readOnlyTx.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
/**
* 必须带事务
* 当前存在事务就使用当前事务,当前不存在事务,就开启一个新的事务
*/
RuleBasedTransactionAttribute requiredTx = new RuleBasedTransactionAttribute();
//检查型异常也回滚
requiredTx.setRollbackRules(
Collections.singletonList(new RollbackRuleAttribute(Exception.class)));
requiredTx.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
requiredTx.setTimeout(TX_METHOD_TIMEOUT);
/***
* 无事务地执行,挂起任何存在的事务
*/
RuleBasedTransactionAttribute noTx = new RuleBasedTransactionAttribute();
noTx.setPropagationBehavior(TransactionDefinition.PROPAGATION_NOT_SUPPORTED);
Map<String, TransactionAttribute> txMap = new HashMap<>();
//只读事务
txMap.put("get*", readOnlyTx);
txMap.put("query*", readOnlyTx);
txMap.put("find*", readOnlyTx);
txMap.put("list*", readOnlyTx);
txMap.put("count*", readOnlyTx);
txMap.put("exist*", readOnlyTx);
txMap.put("search*", readOnlyTx);
txMap.put("fetch*", readOnlyTx);
//无事务
txMap.put("noTx*", noTx);
//写事务
txMap.put("add*", requiredTx);
txMap.put("save*", requiredTx);
txMap.put("insert*", requiredTx);
txMap.put("update*", requiredTx);
txMap.put("modify*", requiredTx);
txMap.put("delete*", requiredTx);
NameMatchTransactionAttributeSource source = new NameMatchTransactionAttributeSource();
source.setNameMap(txMap);
return new TransactionInterceptor(transactionManager, source);
}
@Autowired
BeanFactoryTransactionAttributeSourceAdvisor beanFactoryTransactionAttributeSourceAdvisor;
// 项目启动之后对BeanFactoryTransactionAttributeSourceAdvisor属性进行覆盖。
@Override
public void onApplicationEvent(ApplicationStartedEvent applicationStartedEvent) {
AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
pointcut.setExpression(AOP_POINTCUT_EXPRESSION);
beanFactoryTransactionAttributeSourceAdvisor.setAdvice(txAdvice());
beanFactoryTransactionAttributeSourceAdvisor.setClassFilter(pointcut);
}
}
上述是全局配置事务,如果不想全局配置事务可以在每个需要使用事务的时候手动指定注解配置即可。
注意:使用全局事务也需要搭配
@Transactional
注解进行使用,不然默认也是不生效的
事务监听
自 SpringFramework4.2 之后,出现了一种能在事务动作发生前后注入监听器的机制。
举几个应用场景的例子:
执行完数据库操作后发送消息
执行数据库操作之前记录日志
业务逻辑出错时事务回滚之后发邮件警报
类似于这种事务动作执行前后进行附加操作的问题,在SpringFramework4.2之后就可以通过 @TransactionalEventListener 注解来实现。
@TransactionalEventListener 可提供4种监听时机,来执行附加操作:
BEFORE_COMMIT:提交之前
AFTER_COMMIT:提交之后
AFTER_ROLLBACK:回滚之后
AFTER_COMPLETION:事务完成之后
- 创建listener
@Component
public class TransactionListener {
@TransactionalEventListener(phase = TransactionPhase.AFTER_COMMIT)
private void onTestEvent(UserCleanEvent event) {
System.out.println("UserCleanEvent detected ......" + event);
}
}
- 创建Event
// 定义 用户清除事件,它需要继承ApplicationEvent
public class UserCleanEvent extends ApplicationEvent {
public UserCleanEvent(Object source) {
super(source);
}
}
- 调用代码
@Transactional(rollbackFor = Exception.class)
public void test() {
// 执行清空用户的数据库操作
userDao.deleteAll();
// 使用事件广播器来广播 用户清除事件
applicationEventPublisher.publishEvent(new UserCleanEvent());
}
源码解析
Springboot 预加载事务管理器以及事务拦截器
看完上面的内容之后,我们知道加入Springboot事务管理器的最便捷方法和默认启用的方法是使用@EnableTransactionManagement
注解。那么这个注解干了哪些事情呢?我们看一下:
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(TransactionManagementConfigurationSelector.class)
public @interface EnableTransactionManagement {
boolean proxyTargetClass() default false;
AdviceMode mode() default AdviceMode.PROXY;
int order() default Ordered.LOWEST_PRECEDENCE;
}
我们都知道Springboot实现事务是通过AOP增强实现的,我们可以看到事务默认使用的是AdviceMode.PROXY(Java动态代理)。
@EnableTransactionManagement
加载了一个TransactionManagementConfigurationSelector
这个Selector,如果我们看过一些其他组件的源码都会知道这个是Spring的配置选择器。我们看下选择器如何选择我们需要的配置的。
@Override
protected String[] selectImports(AdviceMode adviceMode) {
switch (adviceMode) {
case PROXY:
return new String[] {AutoProxyRegistrar.class.getName(),
ProxyTransactionManagementConfiguration.class.getName()};
case ASPECTJ:
return new String[] {determineTransactionAspectClass()};
default:
return null;
}
}
可以看到我们PROXY 默认使用了ProxyTransactionManagementConfiguration
这个配置类进行加载事务配置。AspectJ其实也差不多这里不做过多讨论,只讨论Java动态代理实现事务增强。
AutoProxyRegistrar
public class AutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
boolean candidateFound = false;
Set<String> annoTypes = importingClassMetadata.getAnnotationTypes();
for (String annoType : annoTypes) {
AnnotationAttributes candidate = AnnotationConfigUtils.attributesFor(importingClassMetadata, annoType);
if (candidate == null) {
continue;
}
Object mode = candidate.get("mode");
Object proxyTargetClass = candidate.get("proxyTargetClass");
if (mode != null && proxyTargetClass != null && AdviceMode.class == mode.getClass() &&
Boolean.class == proxyTargetClass.getClass()) {
candidateFound = true;
// PROXY模式下会额外注册Bean
if (mode == AdviceMode.PROXY) {
AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
if ((Boolean) proxyTargetClass) {
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
return;
}
}
}
}
if (!candidateFound) {
String name = getClass().getSimpleName();
// logger......
}
}
}
注意中间部分的一个if判断(已用注释标明):如果 @EnableTransactionManagement
注解中设置 adviceMode 为 PROXY (默认PROXY),则会利用 AopUtils 创建组件,并且如果 @EnableTransactionManagement
设置 proxyTargetClass 为true,则还会额外导入组件(默认为false)。下面咱看看它又向容器里注册了什么组件。
@Nullable
public static BeanDefinition registerAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
return registerAutoProxyCreatorIfNecessary(registry, null);
}
→ 继续往下看
AopConfigUtils
@Nullable
public static BeanDefinition registerAutoProxyCreatorIfNecessary(
BeanDefinitionRegistry registry, @Nullable Object source) {
return registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source);
}
→ 继续往下看
AopConfigUtils
@Nullable
private static BeanDefinition registerOrEscalateApcAsRequired(
Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
int requiredPriority = findPriorityForClass(cls);
if (currentPriority < requiredPriority) {
apcDefinition.setBeanClassName(cls.getName());
}
}
return null;
}
RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
beanDefinition.setSource(source);
beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
// 这里是重点他会往BeanDefinition中注册一个InfrastructureAdvisorAutoProxyCreator
registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
return beanDefinition;
}
从上面的方法一级一级向下执行,最终来到 registerOrEscalateApcAsRequired
方法(注意在第二层方法中传入了一个 InfrastructureAdvisorAutoProxyCreator.class
(基础增强器自动代理创建器),可能下面就是注册这个类型的组件)。
InfrastructureAdvisorAutoProxyCreator
可以发现它也是个后置处理器,并且是在Bean创建前后执行的后置处理器(InstantiationAwareBeanPostProcessor),而且它来自 spring-aop 包。那既然是这样,它该类/父类中一定会有寻找增强器、过滤增强器,最终生成代理包装Bean为代理对象的方法。
回到上面的 AopUtils 类,registerAutoProxyCreatorIfNecessary
方法注册了一个 InfrastructureAdvisorAutoProxyCreator
,跟之前咱在AOP部分看到的 @EnableAspectJAutoProxy
注解注册的· AnnotationAwareAspectJAutoProxyCreator· 几乎完全一致了,那下面的方法也不用看了,思路真的完全一致。
上面还注册了一个ProxyTransactionManagementConfiguration
,我们看下这个配置类做了哪些工作!
@Configuration(proxyBeanMethods = false)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {
@Bean(name = TransactionManagementConfigUtils.TRANSACTION_ADVISOR_BEAN_NAME)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public BeanFactoryTransactionAttributeSourceAdvisor transactionAdvisor(
TransactionAttributeSource transactionAttributeSource, TransactionInterceptor transactionInterceptor) {
BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
advisor.setTransactionAttributeSource(transactionAttributeSource);
advisor.setAdvice(transactionInterceptor);
if (this.enableTx != null) {
advisor.setOrder(this.enableTx.<Integer>getNumber("order"));
}
return advisor;
}
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public TransactionAttributeSource transactionAttributeSource() {
// AnnotationTransactionAttributeSource 创建 ①
return new AnnotationTransactionAttributeSource();
}
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public TransactionInterceptor transactionInterceptor(TransactionAttributeSource transactionAttributeSource) {
TransactionInterceptor interceptor = new TransactionInterceptor();
interceptor.setTransactionAttributeSource(transactionAttributeSource);
if (this.txManager != null) {
interceptor.setTransactionManager(this.txManager);
}
return interceptor;
}
}
认真看完上面文章的同学可能已经发现了,BeanFactoryTransactionAttributeSourceAdvisor
就是在在这里进行注入的,我们上面修改默认的事务传递规则就是通过Springboot启动完成事件进行覆盖这个Bean的。他还注意了一个默认的TransactionInterceptor
,我们进行了覆盖。
BeanFactoryTransactionAttributeSourceAdvisor
public class BeanFactoryTransactionAttributeSourceAdvisor extends AbstractBeanFactoryPointcutAdvisor {
@Nullable
private TransactionAttributeSource transactionAttributeSource;
//
private final TransactionAttributeSourcePointcut pointcut = new TransactionAttributeSourcePointcut() {
@Override
@Nullable
protected TransactionAttributeSource getTransactionAttributeSource() {
return transactionAttributeSource;
}
};
/**
* Set the transaction attribute source which is used to find transaction
* attributes. This should usually be identical to the source reference
* set on the transaction interceptor itself.
* @see TransactionInterceptor#setTransactionAttributeSource
*/
public void setTransactionAttributeSource(TransactionAttributeSource transactionAttributeSource) {
this.transactionAttributeSource = transactionAttributeSource;
}
/**
* 我们上面自定义TransactionInterceptor就是通过设置ClassFilter来筛选
* 我们需要拦截的Bean的
*/
public void setClassFilter(ClassFilter classFilter) {
this.pointcut.setClassFilter(classFilter);
}
@Override
public Pointcut getPointcut() {
return this.pointcut;
}
}
从这部分源码中可以得知非常关键的点:它是利用切入点来增强方法 (源码中看到了pointcut)。源码中的pointcut属性的创建又要借助 TransactionAttributeSource 。这部分依赖关系如下:
Advisor → → →依赖→ → → Pointcut → → →依赖→ → → Source
abstract class TransactionAttributeSourcePointcut extends StaticMethodMatcherPointcut implements Serializable {
@Override
public boolean matches(Method method, Class<?> targetClass) {
if (TransactionalProxy.class.isAssignableFrom(targetClass) ||
PlatformTransactionManager.class.isAssignableFrom(targetClass) ||
PersistenceExceptionTranslator.class.isAssignableFrom(targetClass)) {
return false;
}
TransactionAttributeSource tas = getTransactionAttributeSource();
return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);
}
它实现了ClassFilter
接口(matches 是重写的方法,源码不再展开),matches
方法有两部分判断逻辑:是否为 TransactionalProxy
、PlatformTransactionManager
、PersistenceExceptionTranslator 的实现类,以及让 TransactionAttributeSource
获取事务属性看是否为空。前半部分好理解,后半部分需要借助 TransactionAttributeSource
来判断,正好配置类中事务增强器的下边就要创建一个AnnotationTransactionAttributeSource
对应上述①。
AnnotationTransactionAttributeSource
此类读取Spring的 @Transactional 注解,并将相应的事务属性公开给Spring的事务基础结构。此外,还支持JTA 1.2的 javax.transaction.Transactional 和EJB3的 javax.ejb.TransactionAttribute 注解(如果存在)。此类也可用作自定义 TransactionAttributeSource 的基类,或通过 TransactionAnnotationParser 策略进行自定义。
说了这么多,我们只关心一句话:它读取 @Transactional 注解。由此可见 AnnotationTransactionAttributeSource 是读取 @Transactional
注解的。
其构造方法:
public AnnotationTransactionAttributeSource() {
this(true);
}
public AnnotationTransactionAttributeSource(boolean publicMethodsOnly) {
this.publicMethodsOnly = publicMethodsOnly;
this.annotationParsers = new LinkedHashSet<>(2);
this.annotationParsers.add(new SpringTransactionAnnotationParser());
if (jta12Present) {
this.annotationParsers.add(new JtaTransactionAnnotationParser());
}
if (ejb3Present) {
this.annotationParsers.add(new Ejb3TransactionAnnotationParser());
}
}
SpringTransactionAnnotationParser
@Override
@Nullable
public TransactionAttribute parseTransactionAnnotation(AnnotatedElement element) {
AnnotationAttributes attributes = AnnotatedElementUtils.findMergedAnnotationAttributes(
element, Transactional.class, false, false);
if (attributes != null) {
return parseTransactionAnnotation(attributes);
}
else {
return null;
}
}
public TransactionAttribute parseTransactionAnnotation(Transactional ann) {
return parseTransactionAnnotation(AnnotationUtils.getAnnotationAttributes(ann, false, false));
}
protected TransactionAttribute parseTransactionAnnotation(AnnotationAttributes attributes) {
RuleBasedTransactionAttribute rbta = new RuleBasedTransactionAttribute();
Propagation propagation = attributes.getEnum("propagation");
rbta.setPropagationBehavior(propagation.value());
Isolation isolation = attributes.getEnum("isolation");
rbta.setIsolationLevel(isolation.value());
rbta.setTimeout(attributes.getNumber("timeout").intValue());
rbta.setReadOnly(attributes.getBoolean("readOnly"));
rbta.setQualifier(attributes.getString("value"));
List<RollbackRuleAttribute> rollbackRules = new ArrayList<>();
for (Class<?> rbRule : attributes.getClassArray("rollbackFor")) {
rollbackRules.add(new RollbackRuleAttribute(rbRule));
}
for (String rbRule : attributes.getStringArray("rollbackForClassName")) {
rollbackRules.add(new RollbackRuleAttribute(rbRule));
}
for (Class<?> rbRule : attributes.getClassArray("noRollbackFor")) {
rollbackRules.add(new NoRollbackRuleAttribute(rbRule));
}
for (String rbRule : attributes.getStringArray("noRollbackForClassName")) {
rollbackRules.add(new NoRollbackRuleAttribute(rbRule));
}
rbta.setRollbackRules(rollbackRules);
return rbta;
}
可以看到SpringTransactionAnnotationParser
就是用来解析@Transactional注解的。
TransactionInterceptor
的本质是一个 MethodInterceptor
。
TransactionInterceptor
@Override
@Nullable
public Object invoke(MethodInvocation invocation) throws Throwable {
// Work out the target class: may be {@code null}.
// The TransactionAttributeSource should be passed the target class
// as well as the method, which may be from an interface.
Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);
// Adapt to TransactionAspectSupport's invokeWithinTransaction...
return invokeWithinTransaction(invocation.getMethod(), targetClass, invocation::proceed);
}
我们进入到需要调度的事务方法之前会先执行拦截器invoke
方法。我们看下invokeWithinTransaction
做了哪些操作。
TransactionAspectSupport.invokeWithinTransaction
protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass,
final InvocationCallback invocation) throws Throwable {
// If the transaction attribute is null, the method is non-transactional.
TransactionAttributeSource tas = getTransactionAttributeSource();
final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);
final PlatformTransactionManager tm = determineTransactionManager(txAttr);
final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);
if (txAttr == null || !(tm instanceof CallbackPreferringPlatformTransactionManager)) {
// Standard transaction demarcation with getTransaction and commit/rollback calls.
// 创建事务,在下节会讲这里
TransactionInfo txInfo = createTransactionIfNecessary(tm, txAttr, joinpointIdentification);
Object retVal = null;
try {
// This is an around advice: Invoke the next interceptor in the chain.
// This will normally result in a target object being invoked.
// 调用Bean的代理方法 -> 代理方法调用被代理的bean方法
retVal = invocation.proceedWithInvocation();
}
catch (Throwable ex) {
// target invocation exception
// 报错了进行回滚
completeTransactionAfterThrowing(txInfo, ex);
throw ex;
}
finally {
// 清理缓存,如果有自事务则resume到父事务中
cleanupTransactionInfo(txInfo);
}
// 提交事务
commitTransactionAfterReturning(txInfo);
return retVal;
}
else {
final ThrowableHolder throwableHolder = new ThrowableHolder();
// It's a CallbackPreferringPlatformTransactionManager: pass a TransactionCallback in.
try {
Object result = ((CallbackPreferringPlatformTransactionManager) tm).execute(txAttr, status -> {
TransactionInfo txInfo = prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);
try {
return invocation.proceedWithInvocation();
}
catch (Throwable ex) {
if (txAttr.rollbackOn(ex)) {
// A RuntimeException: will lead to a rollback.
if (ex instanceof RuntimeException) {
throw (RuntimeException) ex;
}
else {
throw new ThrowableHolderException(ex);
}
}
else {
// A normal return value: will lead to a commit.
throwableHolder.throwable = ex;
return null;
}
}
finally {
// 清理释放
cleanupTransactionInfo(txInfo);
}
});
// Check result state: It might indicate a Throwable to rethrow.
if (throwableHolder.throwable != null) {
throw throwableHolder.throwable;
}
return result;
}
catch (ThrowableHolderException ex) {
throw ex.getCause();
}
catch (TransactionSystemException ex2) {
if (throwableHolder.throwable != null) {
logger.error("Application exception overridden by commit exception", throwableHolder.throwable);
ex2.initApplicationException(throwableHolder.throwable);
}
throw ex2;
}
catch (Throwable ex2) {
if (throwableHolder.throwable != null) {
logger.error("Application exception overridden by commit exception", throwableHolder.throwable);
}
throw ex2;
}
}
}
事务传递如何实现
接着上面代码我们继续看,createTransactionIfNecessary
protected TransactionInfo createTransactionIfNecessary(@Nullable PlatformTransactionManager tm,
@Nullable TransactionAttribute txAttr, final String joinpointIdentification) {
// If no name specified, apply method identification as transaction name.
if (txAttr != null && txAttr.getName() == null) {
txAttr = new DelegatingTransactionAttribute(txAttr) {
@Override
public String getName() {
return joinpointIdentification;
}
};
}
TransactionStatus status = null;
if (txAttr != null) {
if (tm != null) {
// 获取事务,这句话非常重要
status = tm.getTransaction(txAttr);
}
else {
if (logger.isDebugEnabled()) {
logger.debug("Skipping transactional joinpoint [" + joinpointIdentification +
"] because no transaction manager has been configured");
}
}
}
return prepareTransactionInfo(tm, txAttr, joinpointIdentification, status);
}
AbstractPlatformTransactionManager.getTransaction
@Override
public final TransactionStatus getTransaction(@Nullable TransactionDefinition definition) throws TransactionException {
//
Object transaction = doGetTransaction(); // ① 绑定connection
// Cache debug flag to avoid repeated checks.
boolean debugEnabled = logger.isDebugEnabled();
// Spring会预加载definition等执行到这里的时候definition肯定不是空的
if (definition == null) {
// Use defaults if no transaction definition given.
definition = new DefaultTransactionDefinition();
}
/**
Check if the given transaction object indicates an existing transaction (that is, a transaction which has already started).
// 如果是已经存在的事务(事务已经启动了)
The result will be evaluated according to the specified propagation behavior for the new transaction. An existing transaction might get suspended (in case of PROPAGATION_REQUIRES_NEW), or the new transaction might participate in the existing one (in case of PROPAGATION_REQUIRED).
// 存在的时候可能要进行suspended (以防:PROPAGATION_REQUIRES_NEW (子事务)),或者一个新事物可能在一个已经存在的事务里边
The default implementation returns false, assuming that participating in existing transactions is generally not supported. Subclasses are of course encouraged to provide such support.
*/
if (isExistingTransaction(transaction)) {
// Existing transaction found -> check propagation behavior to find out how to behave.
// 重点的方法 和下面代码逻辑几乎一直
return handleExistingTransaction(definition, transaction, debugEnabled);
}
// Check definition settings for new transaction.
// 如果timeout的格式不合法直接报错
if (definition.getTimeout() < TransactionDefinition.TIMEOUT_DEFAULT) {
throw new InvalidTimeoutException("Invalid transaction timeout", definition.getTimeout());
}
// No existing transaction found -> check propagation behavior to find out how to proceed.
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_MANDATORY) {
throw new IllegalTransactionStateException(
"No existing transaction found for transaction marked with propagation 'mandatory'");
}
else if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRED ||
definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW ||
definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
SuspendedResourcesHolder suspendedResources = suspend(null); // ②
if (debugEnabled) {
logger.debug("Creating new transaction with name [" + definition.getName() + "]: " + definition);
}
try {
boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
// 创建新的事务
DefaultTransactionStatus status = newTransactionStatus(
definition, transaction, true, newSynchronization, debugEnabled, suspendedResources); // ③
doBegin(transaction, definition); // ④
prepareSynchronization(status, definition);
return status;
}
catch (RuntimeException | Error ex) {
resume(null, suspendedResources);
throw ex;
}
}
else {
// Create "empty" transaction: no actual transaction, but potentially synchronization.
if (definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT && logger.isWarnEnabled()) {
logger.warn("Custom isolation level specified but no actual transaction initiated; " +
"isolation level will effectively be ignored: " + definition);
}
boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
// 如果没有配置任何的事务传递规则或者配置Required,则会使用Required传递规则
return prepareTransactionStatus(definition, null, true, newSynchronization, debugEnabled, null);
}
}
handleExistingTransaction
private TransactionStatus handleExistingTransaction(
TransactionDefinition definition, Object transaction, boolean debugEnabled)
throws TransactionException {
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NEVER) {
throw new IllegalTransactionStateException(
"Existing transaction found for transaction marked with propagation 'never'");
}
// 处理PROPAGATION_NOT_SUPPORTED 【不支持】当前方法不会在事务中运行,如果当前线程中存在事务,则将事务挂起,直到方法运行结束
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NOT_SUPPORTED) {
if (debugEnabled) {
logger.debug("Suspending current transaction");
}
// 先清理连接以及解绑datasource
Object suspendedResources = suspend(transaction);
// 创建新事务
boolean newSynchronization = (getTransactionSynchronization() == SYNCHRONIZATION_ALWAYS);
return prepareTransactionStatus(
definition, null, false, newSynchronization, debugEnabled, suspendedResources); // ⑤
}
// 【新事务】当前方法必须在独立的事务中运行,如果当前线程中已经存在事务,则将该事务挂起,重新开启一个事务,直到方法运行结束再释放之前的事务
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_REQUIRES_NEW) {
if (debugEnabled) {
logger.debug("Suspending current transaction, creating new transaction with name [" +
definition.getName() + "]");
}
// 挂起事务
SuspendedResourcesHolder suspendedResources = suspend(transaction);
try {
// 创建新事物并doBean进行连接datasource绑定,在cleanupTransactionInfo恢复parent事务
return startTransaction(definition, transaction, debugEnabled, suspendedResources); // ⑦
}
catch (RuntimeException | Error beginEx) {
resumeAfterBeginException(transaction, suspendedResources, beginEx);
throw beginEx;
}
}
// 【嵌套】当前方法必须在事务中运行,如果当前线程中存在事务,则将该事务标注保存点,形成嵌套事务。嵌套事务中的子事务出现异常不会影响到父事务保存点之前的操作。
if (definition.getPropagationBehavior() == TransactionDefinition.PROPAGATION_NESTED) {
if (!isNestedTransactionAllowed()) {
throw new NestedTransactionNotSupportedException(
"Transaction manager does not allow nested transactions by default - " +
"specify 'nestedTransactionAllowed' property with value 'true'");
}
if (debugEnabled) {
logger.debug("Creating nested transaction with name [" + definition.getName() + "]");
}
if (useSavepointForNestedTransaction()) {
// Create savepoint within existing Spring-managed transaction,
// through the SavepointManager API implemented by TransactionStatus.
// Usually uses JDBC 3.0 savepoints. Never activates Spring synchronization.
DefaultTransactionStatus status =
prepareTransactionStatus(definition, transaction, false, false, debugEnabled, null);
// 创建保存点,在rollback的时候会回退到上一个保存点
status.createAndHoldSavepoint();
return status;
}
else {
// Nested transaction through nested begin and commit/rollback calls.
// Usually only for JTA: Spring synchronization might get activated here
// in case of a pre-existing JTA transaction.
return startTransaction(definition, transaction, debugEnabled, null); // ⑦
}
}
// Assumably PROPAGATION_SUPPORTS or PROPAGATION_REQUIRED.
if (debugEnabled) {
logger.debug("Participating in existing transaction");
}
if (isValidateExistingTransaction()) {
if (definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT) {
Integer currentIsolationLevel = TransactionSynchronizationManager.getCurrentTransactionIsolationLevel();
if (currentIsolationLevel == null || currentIsolationLevel != definition.getIsolationLevel()) {
Constants isoConstants = DefaultTransactionDefinition.constants;
throw new IllegalTransactionStateException("Participating transaction with definition [" +
definition + "] specifies isolation level which is incompatible with existing transaction: " +
(currentIsolationLevel != null ?
isoConstants.toCode(currentIsolationLevel, DefaultTransactionDefinition.PREFIX_ISOLATION) :
"(unknown)"));
}
}
if (!definition.isReadOnly()) {
if (TransactionSynchronizationManager.isCurrentTransactionReadOnly()) {
throw new IllegalTransactionStateException("Participating transaction with definition [" +
definition + "] is not marked as read-only but existing transaction is");
}
}
}
boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
// 如果没有指定传递类型和指定Required默认使用Required
return prepareTransactionStatus(definition, transaction, false, newSynchronization, debugEnabled, null); // ⑤
}
① 创建一个DataSourceTransactionObject
对象,这里会获取到DataSource中的Connection和DataSourceTransactionObject进行绑定。
protected Object doGetTransaction() {
DataSourceTransactionManager.DataSourceTransactionObject txObject = new DataSourceTransactionManager.DataSourceTransactionObject();
txObject.setSavepointAllowed(this.isNestedTransactionAllowed());
ConnectionHolder conHolder = (ConnectionHolder)TransactionSynchronizationManager.getResource(this.obtainDataSource());
txObject.setConnectionHolder(conHolder, false);
return txObject;
}
② suspend 挂机事务
protected final SuspendedResourcesHolder suspend(@Nullable Object transaction) throws TransactionException {
// if transaction synchronization is active for the current thread. Can be called before register to avoid unnecessary instance creation.
// 如果事务同步的被线程启用,避免在没必要注册到实例之前被调用
if (TransactionSynchronizationManager.isSynchronizationActive()) {
List<TransactionSynchronization> suspendedSynchronizations = doSuspendSynchronization();
try {
Object suspendedResources = null;
if (transaction != null) {
// 挂起事务清理连接
suspendedResources = doSuspend(transaction);
}
// 将事务绑定到TransactionSynchronizationManager
String name = TransactionSynchronizationManager.getCurrentTransactionName();
TransactionSynchronizationManager.setCurrentTransactionName(null);
boolean readOnly = TransactionSynchronizationManager.isCurrentTransactionReadOnly();
TransactionSynchronizationManager.setCurrentTransactionReadOnly(false);
Integer isolationLevel = TransactionSynchronizationManager.getCurrentTransactionIsolationLevel();
TransactionSynchronizationManager.setCurrentTransactionIsolationLevel(null);
boolean wasActive = TransactionSynchronizationManager.isActualTransactionActive();
TransactionSynchronizationManager.setActualTransactionActive(false);
return new SuspendedResourcesHolder(
suspendedResources, suspendedSynchronizations, name, readOnly, isolationLevel, wasActive);
}
catch (RuntimeException | Error ex) {
// doSuspend failed - original transaction is still active...
doResumeSynchronization(suspendedSynchronizations);
throw ex;
}
}
else if (transaction != null) {
// Transaction active but no synchronization active.
// 真正的处理操作
Object suspendedResources = doSuspend(transaction);
return new SuspendedResourcesHolder(suspendedResources);
}
else {
// Neither transaction nor synchronization active.
return null;
}
}
doSuspend
protected Object doSuspend(Object transaction) {
// 强转对象
DataSourceTransactionManager.DataSourceTransactionObject txObject = (DataSourceTransactionManager.DataSourceTransactionObject)transaction;
// 清理连接
txObject.setConnectionHolder((ConnectionHolder)null);
// 和DataSource解绑
return TransactionSynchronizationManager.unbindResource(this.obtainDataSource());
}
obtainDataSource
protected DataSource obtainDataSource() {
DataSource dataSource = this.getDataSource();
Assert.state(dataSource != null, "No DataSource set");
return dataSource;
}
unbindResource
public static Object unbindResource(Object key) throws IllegalStateException {
Object actualKey = TransactionSynchronizationUtils.unwrapResourceIfNecessary(key);
Object value = doUnbindResource(actualKey);
if (value == null) {
throw new IllegalStateException(
"No value for key [" + actualKey + "] bound to thread [" + Thread.currentThread().getName() + "]");
}
return value;
}
③ newTransactionStatus
protected DefaultTransactionStatus newTransactionStatus(
TransactionDefinition definition, @Nullable Object transaction, boolean newTransaction,
boolean newSynchronization, boolean debug, @Nullable Object suspendedResources) {
boolean actualNewSynchronization = newSynchronization &&
!TransactionSynchronizationManager.isSynchronizationActive();
// 创建新的事务状态
return new DefaultTransactionStatus(
transaction, newTransaction, actualNewSynchronization,
definition.isReadOnly(), debug, suspendedResources);
}
④ doBegin
从代码中可以看出doBegin和doSupended是一对相反的操作一个进项绑定datasource和数据库连接,一个是解绑。
protected void doBegin(Object transaction, TransactionDefinition definition) {
DataSourceTransactionManager.DataSourceTransactionObject txObject = (DataSourceTransactionManager.DataSourceTransactionObject)transaction;
Connection con = null;
try {
if (!txObject.hasConnectionHolder() || txObject.getConnectionHolder().isSynchronizedWithTransaction()) {
// 获取连接
Connection newCon = this.obtainDataSource().getConnection();
if (this.logger.isDebugEnabled()) {
this.logger.debug("Acquired Connection [" + newCon + "] for JDBC transaction");
}
// DataSourceTransactionObject 绑定连接
txObject.setConnectionHolder(new ConnectionHolder(newCon), true);
}
txObject.getConnectionHolder().setSynchronizedWithTransaction(true);
con = txObject.getConnectionHolder().getConnection();
Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition);
txObject.setPreviousIsolationLevel(previousIsolationLevel);
txObject.setReadOnly(definition.isReadOnly());
if (con.getAutoCommit()) {
txObject.setMustRestoreAutoCommit(true);
if (this.logger.isDebugEnabled()) {
this.logger.debug("Switching JDBC Connection [" + con + "] to manual commit");
}
// 从这里可以看出如果开启了自动提交,在事务中会把自动提交关闭,在事务运行结束后会把自动提交给打开
con.setAutoCommit(false);
}
this.prepareTransactionalConnection(con, definition);
// 设置事务启动
txObject.getConnectionHolder().setTransactionActive(true);
// 设置事务超时时间
int timeout = this.determineTimeout(definition);
if (timeout != -1) {
txObject.getConnectionHolder().setTimeoutInSeconds(timeout);
}
if (txObject.isNewConnectionHolder()) {
// 绑定datasource
TransactionSynchronizationManager.bindResource(this.obtainDataSource(), txObject.getConnectionHolder());
}
} catch (Throwable var7) {
if (txObject.isNewConnectionHolder()) {
DataSourceUtils.releaseConnection(con, this.obtainDataSource());
txObject.setConnectionHolder((ConnectionHolder)null, false);
}
throw new CannotCreateTransactionException("Could not open JDBC Connection for transaction", var7);
}
}
⑤ prepareTransactionStatus
如果存在事务则挂起事务挂起事务
protected final DefaultTransactionStatus prepareTransactionStatus(
TransactionDefinition definition, @Nullable Object transaction, boolean newTransaction,
boolean newSynchronization, boolean debug, @Nullable Object suspendedResources) {
//创建新的事务状态
DefaultTransactionStatus status = newTransactionStatus(
definition, transaction, newTransaction, newSynchronization, debug, suspendedResources);
// 可以发现这里没有dobegin操作
// 根据需要初始化事务同步
prepareSynchronization(status, definition); // ⑥
return status;
}
⑥ prepareSynchronization
Initialize transaction synchronization as appropriate.根据需要初始化事务同步
protected void prepareSynchronization(DefaultTransactionStatus status, TransactionDefinition definition) {
if (status.isNewSynchronization()) {
TransactionSynchronizationManager.setActualTransactionActive(status.hasTransaction());
TransactionSynchronizationManager.setCurrentTransactionIsolationLevel(
definition.getIsolationLevel() != TransactionDefinition.ISOLATION_DEFAULT ?
definition.getIsolationLevel() : null);
TransactionSynchronizationManager.setCurrentTransactionReadOnly(definition.isReadOnly());
TransactionSynchronizationManager.setCurrentTransactionName(definition.getName());
TransactionSynchronizationManager.initSynchronization();
}
}
⑦ startTransaction
private TransactionStatus startTransaction(TransactionDefinition definition, Object transaction,
boolean debugEnabled, @Nullable SuspendedResourcesHolder suspendedResources) {
boolean newSynchronization = (getTransactionSynchronization() != SYNCHRONIZATION_NEVER);
DefaultTransactionStatus status = newTransactionStatus(
definition, transaction, true, newSynchronization, debugEnabled, suspendedResources);
doBegin(transaction, definition); // ④
prepareSynchronization(status, definition); // ⑥
return status;
}
在获取到了事务对象之后,我们重回createTransactionIfNecessary
,会进行prepareTransactionInfo
预处理事务信息操作。下面看下代码:
prepareTransactionInfo
protected TransactionInfo prepareTransactionInfo(@Nullable PlatformTransactionManager tm,
@Nullable TransactionAttribute txAttr, String joinpointIdentification,
@Nullable TransactionStatus status) {
TransactionInfo txInfo = new TransactionInfo(tm, txAttr, joinpointIdentification);
if (txAttr != null) {
// We need a transaction for this method...
if (logger.isTraceEnabled()) {
logger.trace("Getting transaction for [" + txInfo.getJoinpointIdentification() + "]");
}
// The transaction manager will flag an error if an incompatible tx already exists.
txInfo.newTransactionStatus(status);
}
else {
// The TransactionInfo.hasTransaction() method will return false. We created it only
// to preserve the integrity of the ThreadLocal stack maintained in this class.
if (logger.isTraceEnabled())
logger.trace("Don't need to create transaction for [" + joinpointIdentification +
"]: This method isn't transactional.");
}
// We always bind the TransactionInfo to the thread, even if we didn't create
// a new transaction here. This guarantees that the TransactionInfo stack
// will be managed correctly even if no transaction was created by this aspect.
// 这里会把事务对象绑定到threadlocal中
txInfo.bindToThread();
return txInfo;
}
从这里我们可以看出Springboot事务的实现其实是借助于ThreadLocal.
总结
1.Springboot实际上是借助于ThreadLocal去实现事务控制,事务控制的核心对象就是DataSourceTransactionObject
.
2.Springboot事务其实是自己实现的一套事务控制结合数据库的事务进行整体的事务控制,并非直接的数据库事务的控制。只有请求到数据库才是数据的的事务进行控制
3.Springboot是默认启用事务的
4.Springboot实现事务实际上借助了AOP切面的增强。
5.启用AOP,标注 @EnableAspectJAutoProxy 后会向IOC容器中导入一个 AnnotationAwareAspectJAutoProxyCreator
,它是一个 SmartInstantiationAwareBeanPostProcessor
,可以做组件的 创建前后、初始化前后的后置处理工作 。