Spring事务通过AOP切面来增强目标方法的调用,控制事务的开启、提交和回滚。主要的接口有:
- TransactionManager:Spring事务管理器实现的标志接口,对标准事务和反应式事务都可用;
- TransactionStatus:代表事务的状态,事务代码可以使用它来获取事务的状态,也可以在失败的时候,编码式的请求一个回滚;他还包含了SavepointManager接口,用来访问保存点管理信息;注意只有底层事务管理器支持的时候,才能使用保存点管理器。
- TransactionDefinition:定义符合 Spring 的事务属性的接口,基于类似于 EJB CMT 属性的传播行为定义。
- SavepointManager:定义一个API,以一种通用的方式来编程式管理事务保存点的接口
Spring事务分为两种:编程式事务和声明式事务
- 编程式事务:通过编写事务相关的代码来实现对事务开启、提交和回滚的手动控制
- 声明式事务:一般是通过在方法或者类上面加@Transactional注解来实现
声明式事务主要通过**@EnableTransactionManagement注解声明使用事务,加载配置项;使用@Transactional**注解声明方法或类按事务方式运行
@EnableTransactionManagement@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Import(TransactionManagementConfigurationSelector.class)
public @interface EnableTransactionManagement {
// 是否创建基于CGLIB的子类代理,默认使用标准JAVA的基于接口的JDK代理
boolean proxyTargetClass() default false;
// 事务的advice应该怎么样应用,默认是代理模式
AdviceMode mode() default AdviceMode.PROXY;
// 当多个advice在特定的加入点被使用的时候,他可以定义事务advisor的执行顺序
int order() default Ordered.LOWEST_PRECEDENCE;
}
TransactionManagementConfigurationSelector
该注解上使用@Import导入了TransactionManagementConfigurationSelector相关的配置,TransactionManagementConfigurationSelector类会根据不同的模式(代理模式,切面模式)来加载不同的配置
// 基于导入的配置类中的值选择AbstractTransactionManagementConfiguration的实现 public class TransactionManagementConfigurationSelector extends AdviceModeImportSelector{ // 根据EnableTransactionManagement注解中配置的模式返回配置类 @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; } } private String determineTransactionAspectClass() { return (ClassUtils.isPresent("javax.transaction.Transactional", getClass().getClassLoader()) ? TransactionManagementConfigUtils.JTA_TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME : TransactionManagementConfigUtils.TRANSACTION_ASPECT_CONFIGURATION_CLASS_NAME); } }
代理模式中的AutoProxyRegistrar和ProxyTransactionManagementConfiguration可以创建自动代理、生成BeanFactoryTransactionAttributeSourceAdvisor、TransactionAttributeSource和TransactionInterceptor等事务必要的属性源和拦截器;
AutoProxyRegistrarAutoProxyRegistrar主要是解析@EnableTransactionManagement注解的属性,根据模式等注册自动代理
public class AutoProxyRegistrar implements ImportBeanDefinitionRegistrar {
private final Log logger = LogFactory.getLog(getClass());
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
boolean candidateFound = false;
Set 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) {
AopConfigUtils.registerAutoProxyCreatorIfNecessary(registry);
if ((Boolean) proxyTargetClass) { // 存在代理的目标类
// 类代理强制使用自动代理
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会注册org.springframework.aop.config.internalAutoProxyCreator的bean信息
public abstract class AopConfigUtils {
public static final String AUTO_PROXY_CREATOR_BEAN_NAME = "org.springframework.aop.config.internalAutoProxyCreator";
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);
registry.registerBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME, beanDefinition);
return beanDefinition;
}
}
ProxyTransactionManagementConfiguration
ProxyTransactionManagementConfiguration是一个配置类,他会注册BeanFactoryTransactionAttributeSourceAdvisor、TransactionAttributeSource、TransactionInterceptor这三个bean,下面来看看这三个bean的主要作用
@Configuration(proxyBeanMethods = false)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {
// 由一个TransactionAttributeSource驱动的advisor, 用来为事务方法提供事务advice
@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.getNumber("order"));
}
return advisor;
}
// 被事务拦截器使用,是元数据恢复的策略接口;事务属性相关信息可能来源于配置或元数据
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public TransactionAttributeSource transactionAttributeSource() {
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;
}
}
TransactionInterceptor事务拦截器的继承关系如下图:
MethodInterceptor#invoke方法采用CGLIB动态代理,生成目标方法的子类,可以对目标方法进行拦截,然后就在目标方法的执行前后进行一些特殊的处理
TransactionInterceptor继承了TransactionAspectSupport,并且实现了MethodInterceptor接口,可以拦截事务方法,将方法的逻辑放在事务中执行。
TransactionInterceptor#invoke方法先获取目标类,然后调用父类TransactionAspectSupport#invokeWithinTransaction方法,以事务的方式执行业务逻辑
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);
}
重点看一下TransactionAspectSupport#invokeWithinTransaction方法,他会根据不同的事务类型分别执行对应的处理逻辑,可以支持反应式事务、普通事务和带回调的事务
protected Object invokeWithinTransaction(Method method, @Nullable Class> targetClass,
final InvocationCallback invocation) throws Throwable {
// 如果事务属性为null,那这个方法是非事务的
TransactionAttributeSource tas = getTransactionAttributeSource();
final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);
// 确定事务管理器TM
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)) {
// 创建标准事务
TransactionInfo txInfo = createTransactionIfNecessary(ptm, txAttr, joinpointIdentification);
Object retVal;
try {
// 这是一个环绕advice,会在调用链里调用下一个拦截器;他通常会导致目标方法被调用
// 调用目标方法
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 {
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;
}
}
}
@Transactional
该注解可以标记方法或类,使其以事务的方式运行
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Transactional {
@AliasFor("transactionManager")
String value() default "";
@AliasFor("value")
String transactionManager() default "";
Propagation propagation() default Propagation.REQUIRED;
Isolation isolation() default Isolation.DEFAULT;
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 {};
}



