抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

Spring事务-入口分析

前言

在Spring中,事务有两种实现方式:

  1. 编程式事务管理: 编程式事务管理使用TransactionTemplate可实现更细粒度的事务控制。
  2. 声明式事务管理: 基于Spring AOP实现。其本质是对方法前后进行拦截,然后在目标方法开始之前创建或者加入一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务。

​ 声明式事务管理不需要入侵代码,通过@Transactional就可以进行事务操作,更快捷而且简单(尤其是配合spring boot自动配置,可以说是精简至极!),且大部分业务都可以满足,推荐使用。

​ 其实不管是编程式事务还是声明式事务,最终调用的底层核心代码是一致的。本章分别从编程式、声明式入手,再进入核心源码贯穿式讲解。

事务源码

编程式事务TransactionTemplate

编程式事务,Spring已经给我们提供好了模板类TransactionTemplate,可以很方便的使用,如下图:

​ TransactionTemplate全路径名是:org.springframework.transaction.support.TransactionTemplate。看包名也知道了这是spring对事务的模板类。(spring动不动就是各种Template…),看下类图先:

接口定义

一看,实现了TransactionOperations、InitializingBean这2个接口(熟悉spring源码的知道这个InitializingBean又是老套路),我们来看下接口源码如下:

1
2
3
4
5
6
7
8
9
10
11
12
public interface TransactionOperations {

@Nullable
<T> T execute(TransactionCallback<T> action) throws TransactionException;
}

public interface InitializingBean {

void afterPropertiesSet() throws Exception;
}


​ 如上图,TransactionOperations这个接口用来执行事务的回调方法,InitializingBean这个是典型的spring bean初始化流程中的预留接口,专用用来在bean属性加载完毕时执行的方法。

接口实现

回到正题,TransactionTemplate的2个接口的impl方法做了什么?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
/**
* Bean初始化完成后执行
*/
@Override
public void afterPropertiesSet() {
//如果没有事务管理器报错
if (this.transactionManager == null) {
throw new IllegalArgumentException("Property 'transactionManager' is required");
}
}

/**
* 执行事务
*
* @param action
* @param <T>
* @return
* @throws TransactionException
*/
@Override
@Nullable
public <T> T execute(TransactionCallback<T> action) throws TransactionException {
Assert.state(this.transactionManager != null, "No PlatformTransactionManager set");

// 内部封装好的事务管理器
if (this.transactionManager instanceof CallbackPreferringPlatformTransactionManager) {
return ((CallbackPreferringPlatformTransactionManager) this.transactionManager).execute(this, action);

// 需要手动获取事务,执行方法,提交事务的管理器
} else {
// 1.获取事务状态
TransactionStatus status = this.transactionManager.getTransaction(this);
T result;
try {
// 2.执行业务逻辑
result = action.doInTransaction(status);
} catch (RuntimeException | Error ex) {
// 应用运行时异常或者Error异常 -> 回滚
// Transactional code threw application exception -> rollback
rollbackOnException(status, ex);
throw ex;
} catch (Throwable ex) {
// 未知异常 -> 回滚
// Transactional code threw unexpected exception -> rollback
rollbackOnException(status, ex);
throw new UndeclaredThrowableException(ex, "TransactionCallback threw undeclared checked exception");
}
// 3.事务提交
this.transactionManager.commit(status);
return result;
}
}

实际上afterPropertiesSet只是校验了事务管理器不为空,execute()才是核心方法,execute主要步骤:

  1. getTransaction()获取事务。

  2. doInTransaction()执行业务逻辑,这里就是用户自定义的业务代码。如果是没有返回值的,就是doInTransactionWithoutResult()。

  3. commit()事务提交:调用AbstractPlatformTransactionManager的commit,rollbackOnException()异常回滚:调用AbstractPlatformTransactionManager的rollback(),事务提交回滚。

声明式事务@Transactional

AOP相关概念

申明式事务使用的是spring AOP,即面向切面编程。详细可以参考SpringAOP章节,AOP核心概念如下

  • 通知(Advice):定义了切面(各处业务代码中都需要的逻辑提炼成的一个切面)做什么what+when何时使用。例如:前置通知Before、后置通知After、返回通知After-returning、异常通知After-throwing、环绕通知Around.
  • 连接点(Joint point):程序执行过程中能够插入切面的点,一般有多个。比如调用方式时、抛出异常时。
  • 切点(Pointcut):切点定义了连接点,切点包含多个连接点,即where哪里使用通知.通常指定类+方法 或者 正则表达式来匹配 类和方法名称。
  • 切面(Aspect):切面=通知+切点,即when+where+what何时何地做什么。
  • 引入(Introduction):允许我们向现有的类添加新方法或属性。
  • 织入(Weaving):织入是把切面应用到目标对象并创建新的代理对象的过程。

整体流程

声明式事务整体调用过程,可以抽出2条线:

  1. 使用代理模式,生成代理增强类。

  2. 根据代理事务管理配置类,配置事务的织入,在业务方法前后进行环绕增强,增加一些事务的相关操作。例如获取事务属性、提交事务、回滚事务。

入口

springboot 方式

申明式事务使用@Transactional这种注解的方式,那么我们就从springboot 容器启动时的自动配置载入开始看。在/META-INF/spring.factories中配置文件中查找,如下图:

载入2个关于事务的自动配置类:

  • org.springframework.boot.autoconfigure.transaction.TransactionAutoConfiguration
  • org.springframework.boot.autoconfigure.transaction.jta.JtaAutoConfiguration
TransactionAutoConfiguration

jta咱们就不看了,看一下TransactionAutoConfiguration这个自动配置类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
@Configuration
@ConditionalOnClass(PlatformTransactionManager.class)
@AutoConfigureAfter({ JtaAutoConfiguration.class, HibernateJpaAutoConfiguration.class,
DataSourceTransactionManagerAutoConfiguration.class,
Neo4jDataAutoConfiguration.class })
@EnableConfigurationProperties(TransactionProperties.class)
public class TransactionAutoConfiguration {

@Bean
@ConditionalOnMissingBean
public TransactionManagerCustomizers platformTransactionManagerCustomizers(
ObjectProvider<List<PlatformTransactionManagerCustomizer<?>>> customizers) {
return new TransactionManagerCustomizers(customizers.getIfAvailable());
}

@Configuration
@ConditionalOnSingleCandidate(PlatformTransactionManager.class)
public static class TransactionTemplateConfiguration {

private final PlatformTransactionManager transactionManager;

public TransactionTemplateConfiguration(
PlatformTransactionManager transactionManager) {
this.transactionManager = transactionManager;
}

@Bean
@ConditionalOnMissingBean
public TransactionTemplate transactionTemplate() {
return new TransactionTemplate(this.transactionManager);
}
}

@Configuration
@ConditionalOnBean(PlatformTransactionManager.class)
@ConditionalOnMissingBean(AbstractTransactionManagementConfiguration.class)
public static class EnableTransactionManagementConfiguration {

@Configuration
@EnableTransactionManagement(proxyTargetClass = false)
@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "false", matchIfMissing = false)
public static class JdkDynamicAutoProxyConfiguration {

}

@Configuration
@EnableTransactionManagement(proxyTargetClass = true)
@ConditionalOnProperty(prefix = "spring.aop", name = "proxy-target-class", havingValue = "true", matchIfMissing = true)
public static class CglibAutoProxyConfiguration {

}

}

}
TransactionAutoConfiguration
  • @ConditionalOnClass(PlatformTransactionManager.class)即类路径下包含PlatformTransactionManager这个类时这个自动配置生效,这个类是spring事务的核心包,肯定引入了。

  • @AutoConfigureAfter({ JtaAutoConfiguration.class, HibernateJpaAutoConfiguration.class, DataSourceTransactionManagerAutoConfiguration.class, Neo4jDataAutoConfiguration.class }),这个配置在括号中的4个配置类后才生效。

TransactionTemplateConfiguration
  • @ConditionalOnSingleCandidate(PlatformTransactionManager.class)当能够唯一确定一个PlatformTransactionManager bean时才生效。

  • @ConditionalOnMissingBean如果没有定义TransactionTemplate bean生成一个。

EnableTransactionManagementConfiguration
  • @ConditionalOnBean(PlatformTransactionManager.class)当存在PlatformTransactionManager bean时生效。

  • @ConditionalOnMissingBean(AbstractTransactionManagementConfiguration.class)当没有自定义抽象事务管理器配置类时才生效。(即用户自定义抽象事务管理器配置类会优先,如果没有,就用这个默认事务管理器配置类)

    EnableTransactionManagementConfiguration支持2种代理方式:

    1. JdkDynamicAutoProxyConfiguration:

      • @EnableTransactionManagement(proxyTargetClass = false),即proxyTargetClass = false表示是JDK动态代理支持的是:面向接口代理。

      • @ConditionalOnProperty(prefix = “spring.aop”, name = “proxy-target-class”, havingValue = “false”, matchIfMissing = false),即spring.aop.proxy-target-class=false时生效,且没有这个配置不生效。

    2. CglibAutoProxyConfiguration:

      • @EnableTransactionManagement(proxyTargetClass = true),即proxyTargetClass = true标识Cglib代理支持的是子类继承代理。
      • @ConditionalOnProperty(prefix = “spring.aop”, name = “proxy-target-class”, havingValue = “true”, matchIfMissing = true),即spring.aop.proxy-target-class=true时生效,且没有这个配置默认生效。

注意了,默认没有配置,走的Cglib代理。说明@Transactional注解支持直接加在类上。

Spring注解方式

查看源码首先需要找到入口,根据以前学的spring章节可以知道分为xml以及注解的方式加载,我们这里就以注解的方式开始,xml的方式可以自己阅读源码

@EnableTransactionManagement

该注解是启用事务的注解

用法
1
2
3
4
@Component
@EnableTransactionManagement
public class EnabledTransaction {
}

好吧,看了这么多配置类,终于到了@EnableTransactionManagement这个注解了。

EnableTransactionManagement

Spring入口的注解

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(TransactionManagementConfigurationSelector.class)
public @interface EnableTransactionManagement {

/**
* proxyTargetClass = false表示是JDK动态代理支持接口代理。true表示是Cglib代理支持子类继承代理。
*/
boolean proxyTargetClass() default false;

/**
* 事务通知模式(切面织入方式),默认代理模式(同一个类中方法互相调用拦截器不会生效),可以选择增强型AspectJ
*/
AdviceMode mode() default AdviceMode.PROXY;

/**
* 连接点上有多个通知时,排序,默认最低。值越大优先级越低。
*/
int order() default Ordered.LOWEST_PRECEDENCE;

}

TransactionManagementConfigurationSelector

重点看类注解@Import(TransactionManagementConfigurationSelector.class)

TransactionManagementConfigurationSelector类图如下:

​ 如上图所示,TransactionManagementConfigurationSelector继承自AdviceModeImportSelector实现了ImportSelector接口。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector<EnableTransactionManagement> {

/**
* Returns {@link ProxyTransactionManagementConfiguration} or
* {@code AspectJ(Jta)TransactionManagementConfiguration} for {@code PROXY}
* and {@code ASPECTJ} values of {@link EnableTransactionManagement#mode()},
* respectively.
* <p>
* ConfigurationClassPostProcessor
* ConfigurationClassParser 622行掉的
* 收集beanName,然后封装成beanDefinition对象
*/
@Override
protected String[] selectImports(AdviceMode adviceMode) {
switch (adviceMode) {
case PROXY:
//完成AutoProxyRegistrar以及ProxyTransactionManagementConfiguration的注册
return new String[]{AutoProxyRegistrar.class.getName(),
ProxyTransactionManagementConfiguration.class.getName()};
case ASPECTJ:
return new String[]{determineTransactionAspectClass()};
default:
return null;
}
}

private String determineTransactionAspectClass() {
return (ClassUtils.isPresent("javax.transaction.Transactional", getClass().getClassLoader()) ?
TransactionManagementConfigUtils.JTA_TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME :
TransactionManagementConfigUtils.TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME);
}

}

​ 如上图,最终会执行selectImports方法导入需要加载的类,我们只看proxy模式下,载入了AutoProxyRegistrar、ProxyTransactionManagementConfiguration2个类。

  • AutoProxyRegistrar:给容器中注册一个 InfrastructureAdvisorAutoProxyCreator 组件;利用后置处理器机制在对象创建以后,包装对象,返回一个代理对象(增强器),代理对象执行方法利用拦截器链进行调用;
  • ProxyTransactionManagementConfiguration:就是一个配置类,定义了事务增强器。

AutoProxyRegistrar

先看AutoProxyRegistrar实现了ImportBeanDefinitionRegistrar接口,复写registerBeanDefinitions方法,源码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
public class AutoProxyRegistrar implements ImportBeanDefinitionRegistrar {

private final Log logger = LogFactory.getLog(getClass());

//注册BeanDefinition
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
boolean candidateFound = false;
Set<String> annTypes = importingClassMetadata.getAnnotationTypes();
for (String annType : annTypes) {
AnnotationAttributes candidate = AnnotationConfigUtils.attributesFor(importingClassMetadata, annType);
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;
if (mode == AdviceMode.PROXY) {
//代理模式
//注册事务AOP的入口类InfrastructureAdvisorAutoProxyCreator,实际上这个AOP入口类起不了作用
AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
if ((Boolean) proxyTargetClass) {
//如果是CGLOB子类代理模式
AopConfigUtils.forceAutoProxyCreatorToUseClassProxying(registry);
return;
}
}
}
}
if (!candidateFound && logger.isInfoEnabled()) {
String name = getClass().getSimpleName();
logger.info(String.format("%s was imported but no annotations were found " +
"having both 'mode' and 'proxyTargetClass' attributes of type " +
"AdviceMode and boolean respectively. This means that auto proxy " +
"creator registration and configuration may not have occurred as " +
"intended, and components may not be proxied as expected. Check to " +
"ensure that %s has been @Import'ed on the same class where these " +
"annotations are declared; otherwise remove the import of %s " +
"altogether.", name, name, name));
}
}

}

代理模式:AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);

最终调用的是:registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source);基础构建增强自动代理构造器

registerOrEscalateApcAsRequired

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
@Nullable
public static BeanDefinition registerAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
return registerAutoProxyCreatorIfNecessary(registry, null);
}

@Nullable
public static BeanDefinition registerAutoProxyCreatorIfNecessary(
BeanDefinitionRegistry registry, @Nullable Object source) {

return registerOrEscalateApcAsRequired(InfrastructureAdvisorAutoProxyCreator.class, registry, source);
}

@Nullable
private static BeanDefinition registerOrEscalateApcAsRequired(
Class<?> cls, BeanDefinitionRegistry registry, @Nullable Object source) {

Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
// 1.如果注册表中已经存在beanName=org.springframework.aop.config.internalAutoProxyCreator的bean,则按优先级进行选择。
// beanName=org.springframework.aop.config.internalAutoProxyCreator,可能存在的beanClass有三种,按优先级排序如下:
// InfrastructureAdvisorAutoProxyCreator、AspectJAwareAdvisorAutoProxyCreator、AnnotationAwareAspectJAutoProxyCreator
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
// 拿到已经存在的bean定义
BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
// 如果已经存在的bean的className与当前要注册的bean的className不相同,则按优先级进行选择
if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
// 拿到已经存在的bean的优先级
int currentPriority = findPriorityForClass(apcDefinition.getBeanClassName());
// 拿到当前要注册的bean的优先级
int requiredPriority = findPriorityForClass(cls);
if (currentPriority < requiredPriority) {
// 如果当前要注册的bean的优先级大于已经存在的bean的优先级,则将bean的className替换为当前要注册的bean的className,
apcDefinition.setBeanClassName(cls.getName());
}
// 如果小于,则不做处理
}
// 如果已经存在的bean的className与当前要注册的bean的className相同,则无需进行任何处理
return null;
}

// 2.如果注册表中还不存在,则新建一个Bean定义,并添加到注册表中
RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
beanDefinition.setSource(source);
// 设置了order为最高优先级
beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
beanDefinition.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);
// 注册BeanDefinition,beanName为org.springframework.aop.config.internalAutoProxyCreator
registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
return beanDefinition;
}

APC_PRIORITY_LIST列表如下图:

1
2
3
4
5
6
7
8
9
10
11
12
13
/**
* Stores the auto proxy creator classes in escalation order.
* <p>
* 优先级上升list
*/
private static final List<Class<?>> APC_PRIORITY_LIST = new ArrayList<>(3);

static {
// Set up the escalation list...
APC_PRIORITY_LIST.add(InfrastructureAdvisorAutoProxyCreator.class);
APC_PRIORITY_LIST.add(AspectJAwareAdvisorAutoProxyCreator.class);
APC_PRIORITY_LIST.add(AnnotationAwareAspectJAutoProxyCreator.class);
}

InfrastructureAdvisorAutoProxyCreator

由于InfrastructureAdvisorAutoProxyCreator这个类在list中第一个index=0,requiredPriority最小,不进入,所以没有重置beanClassName,啥都没做,返回null.

InfrastructureAdvisorAutoProxyCreator类图如下:

看2个核心方法:InstantiationAwareBeanPostProcessor接口的postProcessBeforeInstantiation实例化前+BeanPostProcessor接口的postProcessAfterInitialization初始化后。

postProcessAfterInitialization
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
@Override
public Object postProcessBeforeInstantiation(Class<?> beanClass, String beanName) {
Object cacheKey = getCacheKey(beanClass, beanName);

if (!StringUtils.hasLength(beanName) || !this.targetSourcedBeans.contains(beanName)) {
//如果已经存在直接返回
if (this.advisedBeans.containsKey(cacheKey)) {
return null;
}
//是否基础构件(基础构建不需要代理):Advice、Pointcut、Advisor、AopInfrastructureBean这四类都算基础构建
if (isInfrastructureClass(beanClass) || shouldSkip(beanClass, beanName)) {
//添加进advisedBeans ConcurrentHashMap<k=Object,v=Boolean>标记是否需要增强实现,这里基础构建bean不需要代理,都置为false,供后面postProcessAfterInitialization实例化后使用。
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return null;
}
}

// TargetSource是spring aop预留给我们用户自定义实例化的接口,如果存在TargetSource就不会默认实例化,而是按照用户自定义的方式实例化,咱们没有定义,不进入
// Create proxy here if we have a custom TargetSource.
// Suppresses unnecessary default instantiation of the target bean:
// The TargetSource will handle target instances in a custom fashion.
TargetSource targetSource = getCustomTargetSource(beanClass, beanName);
if (targetSource != null) {
if (StringUtils.hasLength(beanName)) {
this.targetSourcedBeans.add(beanName);
}
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(beanClass, beanName, targetSource);
Object proxy = createProxy(beanClass, beanName, specificInterceptors, targetSource);
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}

return null;
}

通过追踪,由于InfrastructureAdvisorAutoProxyCreator是基础构建类,

advisedBeans.put(cacheKey, Boolean.FALSE)

添加进advisedBeans ConcurrentHashMap<k=Object,v=Boolean>标记是否需要增强实现,这里基础构建bean不需要代理,都置为false,供后面postProcessAfterInitialization实例化后使用。

postProcessAfterInitialization
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/**
* 创建Bean的代理的入口
* Create a proxy with the configured interceptors if the bean is
* identified as one to proxy by the subclass.
*
* @see #getAdvicesAndAdvisorsForBean
*/
@Override
public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
if (bean != null) {
//从缓存中获取代理实例
Object cacheKey = getCacheKey(bean.getClass(), beanName);
// 1.判断当前bean是否需要被代理,如果需要则进行封装
if (this.earlyProxyReferences.remove(cacheKey) != bean) {
//如果需要包装成代理实例
return wrapIfNecessary(bean, beanName, cacheKey);
}
}
return bean;
}

到此位置已经到了AOP的部分内容了,详细可以参考AOP源码解析

ProxyTransactionManagementConfiguration

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
@Configuration(proxyBeanMethods = false)
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {

/**
* 定义事务增强器
* 明显是创建事务切面实例
*
* @param transactionAttributeSource
* @param transactionInterceptor
* @return
*/
@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;
}

/**
* 定义基于注解的事务属性资源
* @return
*/
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public TransactionAttributeSource transactionAttributeSource() {
return new AnnotationTransactionAttributeSource();
}

/**
* 定义事务拦截器
* 创建事务advice
* TransactionInterceptor
* @param transactionAttributeSource
* @return
*/
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public TransactionInterceptor transactionInterceptor(
TransactionAttributeSource transactionAttributeSource) {
//创建事务拦截器
TransactionInterceptor interceptor = new TransactionInterceptor();
//将事务拦截器加入到 AOP拦截器链
interceptor.setTransactionAttributeSource(transactionAttributeSource);
//事务管理器要跟数据源挂钩,所以需要自己定义
if (this.txManager != null) {
interceptor.setTransactionManager(this.txManager);
}
return interceptor;
}
}

核心方法:transactionAdvisor()事务织入

定义了一个advisor,设置事务属性、设置事务拦截器TransactionInterceptor、设置顺序。核心就是事务拦截器TransactionInterceptor。

TransactionInterceptor

TransactionInterceptor使用通用的spring事务基础架构实现“声明式事务”,继承自TransactionAspectSupport类(该类包含与Spring的底层事务API的集成),实现了MethodInterceptor接口。

spring类图如下:

​ 事务拦截器的拦截功能就是依靠实现了MethodInterceptor接口,熟悉spring的同学肯定很熟悉MethodInterceptor了,这个是spring的方法拦截器,主要看invoke方法:

invoke
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/**
* AOP 调用的入口
* @param invocation
* @return
* @throws Throwable
*/
@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);


//调用TransactionAspectSupport的 invokeWithinTransaction方法,开始执行事务
// Adapt to TransactionAspectSupport's invokeWithinTransaction...
return invokeWithinTransaction(invocation.getMethod(), targetClass, invocation::proceed);
}

​ 如上图TransactionInterceptor复写MethodInterceptor接口的invoke方法,并在invoke方法中调用了父类TransactionAspectSupport的invokeWithinTransaction()方法,源码如下:

invokeWithinTransaction
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
@Nullable
protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass,
final InvocationCallback invocation) throws Throwable {

// If the transaction attribute is null, the method is non-transactional.

//获取事务属性类 AnnotationTransactionAttributeSource
TransactionAttributeSource tas = getTransactionAttributeSource();

//获取方法上面有@Transactional注解的属性
// 如果transaction attribute为空,该方法就是非事务(非编程式事务)
final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);

//获取事务管理器
final TransactionManager tm = determineTransactionManager(txAttr);

// 标准声明式事务:如果事务属性为空 或者 非回调偏向的事务管理器
if (this.reactiveAdapterRegistry != null && tm instanceof ReactiveTransactionManager) {
ReactiveTransactionSupport txSupport = this.transactionSupportCache.computeIfAbsent(method, key -> {
if (KotlinDetector.isKotlinType(method.getDeclaringClass()) && KotlinDelegate.isSuspend(method)) {
throw new TransactionUsageException(
"Unsupported annotated transaction on suspending function detected: " + method +
". Use TransactionalOperator.transactional extensions instead.");
}
ReactiveAdapter adapter = this.reactiveAdapterRegistry.getAdapter(method.getReturnType());
if (adapter == null) {
throw new IllegalStateException("Cannot apply reactive transaction to non-reactive return type: " +
method.getReturnType());
}
return new ReactiveTransactionSupport(adapter);
});
return txSupport.invokeWithinTransaction(
method, targetClass, invocation, txAttr, (ReactiveTransactionManager) tm);
}

PlatformTransactionManager ptm = asPlatformTransactionManager(tm);
final String joinpointIdentification = methodIdentification(method, targetClass, txAttr);

if (txAttr == null || !(ptm instanceof CallbackPreferringPlatformTransactionManager)) {
// Standard transaction demarcation with getTransaction and commit/rollback calls.
//创建事务
TransactionInfo txInfo = createTransactionIfNecessary(ptm, txAttr, joinpointIdentification);

Object retVal;
try {
// This is an around advice: Invoke the next interceptor in the chain.
// This will normally result in a target object being invoked.
//火炬传递
// 这里就是一个环绕增强,在这个proceed前后可以自己定义增强实现
retVal = invocation.proceedWithInvocation();
} catch (Throwable ex) {
// target invocation exception
// 根据事务定义的,该异常需要回滚就回滚,否则提交事务
completeTransactionAfterThrowing(txInfo, ex);
throw ex;
} finally {
//清空当前事务信息,重置为老的
cleanupTransactionInfo(txInfo);
}

if (vavrPresent && VavrDelegate.isVavrTry(retVal)) {
// Set rollback-only in case of Vavr failure matching our rollback rules...
TransactionStatus status = txInfo.getTransactionStatus();
if (status != null && txAttr != null) {
retVal = VavrDelegate.evaluateTryFailure(retVal, txAttr, status);
}
}
//返回结果之前提交事务
commitTransactionAfterReturning(txInfo);
return retVal;

//编程式事务:(回调偏向)
} else {
final ThrowableHolder throwableHolder = new ThrowableHolder();

// It's a CallbackPreferringPlatformTransactionManager: pass a TransactionCallback in.
try {
Object result = ((CallbackPreferringPlatformTransactionManager) ptm).execute(txAttr, status -> {
TransactionInfo txInfo = prepareTransactionInfo(ptm, txAttr, joinpointIdentification, status);
try {
Object retVal = invocation.proceedWithInvocation();
if (vavrPresent && VavrDelegate.isVavrTry(retVal)) {
// Set rollback-only in case of Vavr failure matching our rollback rules...
retVal = VavrDelegate.evaluateTryFailure(retVal, txAttr, status);
}
return retVal;
} catch (Throwable ex) {
// 如果该异常需要回滚
if (txAttr.rollbackOn(ex)) {
// A RuntimeException: will lead to a rollback.
if (ex instanceof RuntimeException) {
// 如果是运行时异常返回
throw (RuntimeException) ex;
} else {
// 如果是其它异常都抛ThrowableHolderException
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;
}
}
}

我们主要看第一个分支,声明式事务,核心流程如下:

  1. createTransactionIfNecessary():如果有必要,创建事务

  2. InvocationCallback的proceedWithInvocation():InvocationCallback是父类的内部回调接口,子类中实现该接口供父类调用,子类TransactionInterceptor中invocation.proceed()。回调方法执行

  3. 异常回滚completeTransactionAfterThrowing()

createTransactionIfNecessary

如果需要就创建事务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
protected TransactionInfo createTransactionIfNecessary(@Nullable PlatformTransactionManager tm,
@Nullable TransactionAttribute txAttr, final String joinpointIdentification) {

// If no name specified, apply method identification as transaction name.
// 如果还没有定义名字,把连接点的ID定义成事务的名称
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);
}

核心就是:

  1. getTransaction(),根据事务属性获取事务TransactionStatus,大道归一,都是调用PlatformTransactionManager.getTransaction(),源码见3.3.1。
  2. prepareTransactionInfo(),构造一个TransactionInfo事务信息对象,绑定当前线程:ThreadLocal<TransactionInfo>。
invocation.proceedWithInvocation

回调业务方法,最终实现类是ReflectiveMethodInvocation,类图如下:

ReflectiveMethodInvocation类实现了ProxyMethodInvocation接口,但是ProxyMethodInvocation继承了3层接口…ProxyMethodInvocation->MethodInvocation->Invocation->Joinpoint

  • Joinpoint:连接点接口,定义了执行接口:Object proceed() throws Throwable; 执行当前连接点,并跳到拦截器链上的下一个拦截器。

  • Invocation:调用接口,继承自Joinpoint,定义了获取参数接口: Object[] getArguments();是一个带参数的、可被拦截器拦截的连接点。

  • MethodInvocation:方法调用接口,继承自Invocation,定义了获取方法接口:Method getMethod(); 是一个带参数的可被拦截的连接点方法。

  • ProxyMethodInvocation:代理方法调用接口,继承自MethodInvocation,定义了获取代理对象接口:Object getProxy();是一个由代理类执行的方法调用连接点方法。

  • ReflectiveMethodInvocation:实现了ProxyMethodInvocation接口,自然就实现了父类接口的的所有接口。获取代理类,获取方法,获取参数,用代理类执行这个方法并且自动跳到下一个连接点。

下面看一下proceed方法源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
@Override
@Nullable
public Object proceed() throws Throwable {
// We start with an index of -1 and increment early.
// 1.如果所有拦截器都执行完毕(index是从-1开始,所以跟size - 1比较),则直接使用反射调用连接点(也就是我们原本的方法)
//如果执行链中的advice全部执行完,则直接调用joinPoint方法,就是被代理方法
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return invokeJoinpoint();
}

// 2.每次调用时,将索引的值递增,并通过索引拿到要执行的拦截器
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
// 3.判断拦截器是否为InterceptorAndDynamicMethodMatcher类型(动态方法匹配拦截器)
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
// Evaluate dynamic method matcher here: static part will already have
// been evaluated and found to match.
// 进行动态匹配。在此评估动态方法匹配器:静态部件已经过评估并且发现匹配。
InterceptorAndDynamicMethodMatcher dm =
(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass());
if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) {
return dm.interceptor.invoke(this);
}
else {
// Dynamic matching failed.
// Skip this interceptor and invoke the next in the chain.
// 动态匹配失败。跳过此拦截器并调用链中的下一个。
return proceed();
}
}
else {
// It's an interceptor, so we just invoke it: The pointcut will have
// been evaluated statically before this object was constructed.
// 4.只是一个普通的拦截器,则触发拦截器链责任链的调用,并且参数为ReflectiveMethodInvocation本身
//调用MethodInterceptor中的invoke方法
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}

咱们这里最终调用的是((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);就是TransactionInterceptor事务拦截器回调 目标业务方法(addUserBalanceAndUser)。

completeTransactionAfterThrowing

最终调用AbstractPlatformTransactionManager的rollback(),提交事务commitTransactionAfterReturning()最终调用AbstractPlatformTransactionManager的commit()。

评论