在使用事务的时候需要添加@EnableTransactionManagement注解来开启事务,那么就从@EnableTransactionManagement入手查看一下事务的执行原理。

@EnableTransactionManagement

  1. Spring事务底层是通过AOP来完成的,而Spring AOP基于动态代理实现,可以看到mode方法默认返回了PROXY代理模式,我们只需关注代理模式下的执行流程即可
  2. 使用@Import导入了TransactionManagementConfigurationSelector
@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;
}

TransactionManagementConfigurationSelector

在selectImports方法中可以看到对模式进行了判断:

  1. 如果是基于代理模式,返回AutoProxyRegistrar和ProxyTransactionManagementConfiguration类
  2. 如果是基于ASPECTJ,调用determineTransactionAspectClass方法

Spring默认使用的是代理模式,所以接下来看下AutoProxyRegistrar和ProxyTransactionManagementConfiguration里面都有什么。

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:
// 如果基于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

AutoProxyRegistrar实现了ImportBeanDefinitionRegistrar接口,ImportBeanDefinitionRegistrar可以向容器中注册Bean,跟着registerBeanDefinitions方法看下它会向容器中注册什么样的bean:

public class AutoProxyRegistrar implements ImportBeanDefinitionRegistrar {

        @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) {
// 调用AopConfigUtils的registerAutoProxyCreatorIfNecessary向容器中注册bean
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

在AopConfigUtils中一共有三种自动代理创建器:

  1. InfrastructureAdvisorAutoProxyCreator
  2. AspectJAwareAdvisorAutoProxyCreator
  3. AnnotationAwareAspectJAutoProxyCreator

在registerAutoProxyCreatorIfNecessary方法中,可以看到事务使用的是InfrastructureAdvisorAutoProxyCreator类型的创建器:

public abstract class AopConfigUtils {

	/**
* 自动代理创建器BeanName
*/
public static final String AUTO_PROXY_CREATOR_BEAN_NAME =
"org.springframework.aop.config.internalAutoProxyCreator"; /**
* 所有的自动代理创建器集合
*/
private static final List<Class<?>> APC_PRIORITY_LIST = new ArrayList<>(3); static {
// 初始化
APC_PRIORITY_LIST.add(InfrastructureAdvisorAutoProxyCreator.class);
APC_PRIORITY_LIST.add(AspectJAwareAdvisorAutoProxyCreator.class); // AspectJ
APC_PRIORITY_LIST.add(AnnotationAwareAspectJAutoProxyCreator.class); // 注解
} // AutoProxyRegistrar中调用的registerAutoProxyCreatorIfNecessary方法
@Nullable
public static BeanDefinition registerAutoProxyCreatorIfNecessary(BeanDefinitionRegistry registry) {
// 会调用下面那个registerAutoProxyCreatorIfNecessary方法
return registerAutoProxyCreatorIfNecessary(registry, null);
} @Nullable
public static BeanDefinition registerAutoProxyCreatorIfNecessary(
BeanDefinitionRegistry registry, @Nullable Object source) {
// 调用registerOrEscalateApcAsRequired进行注册,这里传入的是InfrastructureAdvisorAutoProxyCreator类型的
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");
// 判断容器中是否已经包含代理创建器
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
RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
// 设置source
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;
}
}

总结

AutoProxyRegistrar实现ImportBeanDefinitionRegistrar是为了向容器中注册代理创建器,事务默认使用的是InfrastructureAdvisorAutoProxyCreator类型的。

ProxyTransactionManagementConfiguration

1. AOP概念

Advice通知:定义在切点上需要执行什么样的操作

PointCut切点:定义在哪些方法上使用通知

Advisor:Advice和Pointcut加起来组成了Advisor

2. 事务中的Advisor

我们已经知道事务是基于AOP实现的,在transactionAdvisor方法中可以看到创建了Advisor,然后设置了事务属性TransactionAttributeSource和事务拦截器TransactionInterceptor:

  • TransactionAttributeSource,从名字上可以看出是和事务的属性设置相关的
  • TransactionInterceptor事务拦截器相当于Advice通知
  • BeanFactoryTransactionAttributeSourceAdvisor是Advisor

Advisor由Advice和PointCut组成,现在Advice已经有了,接下来看下Pointcut在哪里。

@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) {
// 创建Advisor
BeanFactoryTransactionAttributeSourceAdvisor advisor = new BeanFactoryTransactionAttributeSourceAdvisor();
// 设置TransactionAttributeSource,类型为AnnotationTransactionAttributeSource
advisor.setTransactionAttributeSource(transactionAttributeSource);
// 设置事务拦截器,相当于Advice
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

BeanFactoryTransactionAttributeSourceAdvisor继承关系如下:

除了继承父类的属性和方法,它自己还有两个成员变量:

  1. transactionAttributeSource,实际传入的是AnnotationTransactionAttributeSource类型的对象
  2. TransactionAttributeSourcePointcut类型的切点pointcut
    • 切点在实例化时实现了getTransactionAttributeSource方法,返回了transactionAttributeSource,后面的方法中需要调用此方法获取transactionAttributeSource

由上面的分析可知,在创建BeanFactoryTransactionAttributeSourceAdvisor的时候,设置了TransactionInterceptor和TransactionAttributeSource,TransactionInterceptor相当于Advice,而这里我们看到了它还有一个TransactionAttributeSourcePointcut切点:

public class BeanFactoryTransactionAttributeSourceAdvisor extends AbstractBeanFactoryPointcutAdvisor {

	@Nullable
private TransactionAttributeSource transactionAttributeSource; // 实际传入的是AnnotationTransactionAttributeSource类型的 // 创建切点
private final TransactionAttributeSourcePointcut pointcut = new TransactionAttributeSourcePointcut() { // 实现了getTransactionAttributeSource方法,返回的是AnnotationTransactionAttributeSource
@Override
@Nullable
protected TransactionAttributeSource getTransactionAttributeSource() {
return transactionAttributeSource;
}
}; public void setTransactionAttributeSource(TransactionAttributeSource transactionAttributeSource) {
// 设置TransactionAttributeSource
this.transactionAttributeSource = transactionAttributeSource;
} @Override
public Pointcut getPointcut() {
return this.pointcut;
} }

TransactionAttributeSourcePointcut

TransactionAttributeSourcePointcut是一个切点,它的继承关系如下:

PointcutMethodMatcher

Pointcut接口中定义了两个方法:

  1. 获取ClassFilter,ClassFilter是一个接口,里面定义了matches方法,检查切点是否与类匹配
  2. 获取MethodMatcher,它也是一个接口,并且定义了matches方法,检查切点是否与方法匹配
public interface Pointcut {

	/**
* 返回类过滤器ClassFilter
*/
ClassFilter getClassFilter(); /**
* 返回MethodMatcher
*/
MethodMatcher getMethodMatcher(); } public interface MethodMatcher { /**
* 检查方法是否匹配pointcut
*/
boolean matches(Method method, Class<?> targetClass); /**
* 检查方法是否匹配pointcut
*/
boolean matches(Method method, Class<?> targetClass, Object... args); } @FunctionalInterface
public interface ClassFilter { /**
* 检查类是否与pointcut匹配
*/
boolean matches(Class<?> clazz); }

TransactionAttributeSourcePointcut是Pointcut和MethodMatcher的子类:

  1. 在构造函数中设置了ClassFilter,类型为TransactionAttributeSourceClassFilter,它是TransactionAttributeSourcePointcut的一个内部类,实现了ClassFilter接口中定义的matches方法,检查pointcut与类是否匹配:

    • 如果是TransactionalProxy、PlatformTransactionManager或者PersistenceExceptionTranslator的子类,则不匹配
    • 获取TransactionAttributeSource,调用它的isCandidateClass方法判断是否匹配
  2. 实现了MethodMatcher接口中定义的matches方法,检查pointcut是否匹配当前的方法
    • 获取TransactionAttributeSource判断是否为空,如果不为空则调用getTransactionAttribute获取事务属性,TransactionAttributeSource为空,或者从TransactionAttributeSource获取到的事务属性不为空都会返回true

所以一个方法执行时开启事务,需要满足两个条件,当前的方法和类都需要与事务的pointcut匹配,对应的方法分别是MethodMatcher的matches和ClassFilter的matches方法。

abstract class TransactionAttributeSourcePointcut extends StaticMethodMatcherPointcut implements Serializable {

	protected TransactionAttributeSourcePointcut() {
// 设置ClassFilter
setClassFilter(new TransactionAttributeSourceClassFilter());
} // 方法是否与切点匹配
@Override
public boolean matches(Method method, Class<?> targetClass) {
// 获取TransactionAttributeSource,由上面的步骤可知返回的是AnnotationTransactionAttributeSource
TransactionAttributeSource tas = getTransactionAttributeSource();
// 如果TransactionAttributeSource为空,或者从TransactionAttributeSource获取到的事务属性不为空都会返回true
return (tas == null || tas.getTransactionAttribute(method, targetClass) != null);
} // ClassFilter过滤器
private class TransactionAttributeSourceClassFilter implements ClassFilter { // 切点是否与类匹配
@Override
public boolean matches(Class<?> clazz) {
// 如果TransactionalProxy、PlatformTransactionManager或者PersistenceExceptionTranslator的子类,则不匹配
if (TransactionalProxy.class.isAssignableFrom(clazz) ||
PlatformTransactionManager.class.isAssignableFrom(clazz) ||
PersistenceExceptionTranslator.class.isAssignableFrom(clazz)) {
return false;
}
// 获取TransactionAttributeSource,由上文可知是AnnotationTransactionAttributeSource类型的
TransactionAttributeSource tas = getTransactionAttributeSource();
// 调用isCandidateClass方法判断是否是匹配
return (tas == null || tas.isCandidateClass(clazz));
}
} }

AnnotationTransactionAttributeSource

条件一:检查类是否匹配事务切点

上面分析可知,检查类是否与切点匹配时获取了TransactionAttributeSource,调用它的isCandidateClass方法进行判断,TransactionAttributeSource的具体实现是AnnotationTransactionAttributeSource:

  1. 在构造方法中,添加了注解解析器:

    • Spring事务注解解析器的实现类为SpringTransactionAnnotationParser,也是默认的注解解析器
    • 如果开启了JTA或者EJB,将会分别添加对应的解析器。
  2. 实现了isCandidateClass方法,实际又是调用注解解析器的isCandidateClass判断是否是候选类的。
@SuppressWarnings("serial")
public class AnnotationTransactionAttributeSource extends AbstractFallbackTransactionAttributeSource
implements Serializable { private static final boolean jta12Present; private static final boolean ejb3Present; static {
ClassLoader classLoader = AnnotationTransactionAttributeSource.class.getClassLoader();
jta12Present = ClassUtils.isPresent("javax.transaction.Transactional", classLoader);
ejb3Present = ClassUtils.isPresent("javax.ejb.TransactionAttribute", classLoader);
} private final boolean publicMethodsOnly;
// 注解解析器集合
private final Set<TransactionAnnotationParser> annotationParsers; public AnnotationTransactionAttributeSource(boolean publicMethodsOnly) {
this.publicMethodsOnly = publicMethodsOnly;
// 添加注解解析器
if (jta12Present || ejb3Present) {
this.annotationParsers = new LinkedHashSet<>(4);
// 添加Spring事务注解解析器
this.annotationParsers.add(new SpringTransactionAnnotationParser());
if (jta12Present) {
// JTA事务注解解析器
this.annotationParsers.add(new JtaTransactionAnnotationParser());
}
if (ejb3Present) {
// EJB3事务注解解析器
this.annotationParsers.add(new Ejb3TransactionAnnotationParser());
}
}
else {
// 添加Spring事务注解解析器
this.annotationParsers = Collections.singleton(new SpringTransactionAnnotationParser());
}
} // 判断是否是候选类
@Override
public boolean isCandidateClass(Class<?> targetClass) {
for (TransactionAnnotationParser parser : this.annotationParsers) {
// 调用解析器的isCandidateClass方法判断是否是候选类
if (parser.isCandidateClass(targetClass)) {
return true;
}
}
return false;
} }

SpringTransactionAnnotationParser

  1. SpringTransactionAnnotationParser实现了isCandidateClass方法,它又调用了AnnotationUtils的isCandidateClass判断目标类是否是Transactional注解的候选类,AnnotationUtils中isCandidateClass的具体判断逻辑如下:

    • 如果注解类路径以java.开头,返回true,这里Transactional注解不是java.开头,它是Spring的注解类,所以这个条件不会成立

    • 如果目标类的类路径以java.开头,或者是Ordered类型,isCandidateClass返回false,说明目标类不是某个注解的候选类

    • 除去以上两种情况之外,isCandidateClass都返回true

      总结: 如果目标类的类路径不以java.开头(也就是说它不是java的相关类),也不是Ordered类型,说明目标类是Transactional注解的候选类。

  2. SpringTransactionAnnotationParser实现了parseTransactionAnnotation方法,里面包含对事物属性的解析

public class SpringTransactionAnnotationParser implements TransactionAnnotationParser, Serializable {

	@Override
public boolean isCandidateClass(Class<?> targetClass) {
// 是否是Transactional注解的候选类
return AnnotationUtils.isCandidateClass(targetClass, Transactional.class);
} // 解析注解属性
@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;
} } // AnnotationUtils
public abstract class AnnotationUtils { /**
* 检查目标类clazz是否是注解的候选类
*/
public static boolean isCandidateClass(Class<?> clazz, Collection<Class<? extends Annotation>> annotationTypes) {
for (Class<? extends Annotation> annotationType : annotationTypes) {
// 传入目标类和注解,SpringTransactionAnnotationParser传入的注解是Transactional
if (isCandidateClass(clazz, annotationType)) {
return true;
}
}
return false;
} /**
* 检查目标类clazz是否是注解的候选类
*/
public static boolean isCandidateClass(Class<?> clazz, Class<? extends Annotation> annotationType) {
// 传入目标类和注解类路径
return isCandidateClass(clazz, annotationType.getName());
} /**
* 检查目标类clazz是否是注解的候选类
*/
public static boolean isCandidateClass(Class<?> clazz, String annotationName) {
// 注解类路径是否是java.开头
if (annotationName.startsWith("java.")) {
return true;
}
// 调用AnnotationsScanner的hasPlainJavaAnnotationsOnly方法判断
// hasPlainJavaAnnotationsOnly方法的判断逻辑是:如果目标类的类路径以java.开头或者是Ordered类会返回true
// 所以如果目标类的类路径以java.开头或者是Ordered类,isCandidateClass会返回false,说明目标类不是注解的候选类
if (AnnotationsScanner.hasPlainJavaAnnotationsOnly(clazz)) {
return false;
}
// 如果注解类路径不是java.开头,并且目标类的类路径不以java.开头,也不是Ordered类型,返回true,说明目标类是某个注解的候选类
return true;
}
} // AnnotationsScanner
abstract class AnnotationsScanner {
static boolean hasPlainJavaAnnotationsOnly(Class<?> type) {
// 如果目标类的类路径以java.开头或者是Ordered类
return (type.getName().startsWith("java.") || type == Ordered.class);
}
}

条件二:检查方法是否匹配事务切点

AbstractFallbackTransactionAttributeSource

如果从TransactionAttributeSource获取到的事务属性不为空将会满足切点的匹配条件,获取事务属性的方法实现在AbstractFallbackTransactionAttributeSource类中:

  1. 如果当前方法是Object中的方法,返回空
  2. 根据当前的方法和类的信息构建缓存key,从缓存中获取
    • 如果获取不为空,判断是否为空的事务属性NULL_TRANSACTION_ATTRIBUTE,如果是则返回null,否则返回从缓存中获取到的事务属性
    • 如果获取为空,调用解析事务属性的方法进行解析,然后放入缓存中并返回
public abstract class AbstractFallbackTransactionAttributeSource implements TransactionAttributeSource {

        // 空的TransactionAttribute
@SuppressWarnings("serial")
private static final TransactionAttribute NULL_TRANSACTION_ATTRIBUTE = new DefaultTransactionAttribute() {
@Override
public String toString() {
return "null";
}
};
// 缓存
private final Map<Object, TransactionAttribute> attributeCache = new ConcurrentHashMap<>(1024); // 获取事务属性
@Override
@Nullable
public TransactionAttribute getTransactionAttribute(Method method, @Nullable Class<?> targetClass) {
// 如果当前方法所在的类是Object
if (method.getDeclaringClass() == Object.class) {
return null;
}
// 构建cacheKey
Object cacheKey = getCacheKey(method, targetClass);
// 首先根据cacheKey从缓存中获取
TransactionAttribute cached = this.attributeCache.get(cacheKey);
if (cached != null) {
// 判断是否为空的TRANSACTION_ATTRIBUTE
if (cached == NULL_TRANSACTION_ATTRIBUTE) {
// 返回空
return null;
}
else {
// 返回事务属性TransactionAttribute
return cached;
}
}
else {
// 解析TransactionAttribute
TransactionAttribute txAttr = computeTransactionAttribute(method, targetClass);
// 如果为空,也加入缓存,但是value是NULL_TRANSACTION_ATTRIBUTE
if (txAttr == null) {
this.attributeCache.put(cacheKey, NULL_TRANSACTION_ATTRIBUTE);
}
else {
String methodIdentification = ClassUtils.getQualifiedMethodName(method, targetClass);
// 如果是DefaultTransactionAttribute类型的
if (txAttr instanceof DefaultTransactionAttribute) {
((DefaultTransactionAttribute) txAttr).setDescriptor(methodIdentification);
}
if (logger.isTraceEnabled()) {
logger.trace("Adding transactional method '" + methodIdentification + "' with attribute: " + txAttr);
}
// 加入缓存
this.attributeCache.put(cacheKey, txAttr);
}
return txAttr;
}
} // 获取缓存KEY
protected Object getCacheKey(Method method, @Nullable Class<?> targetClass) {
return new MethodClassKey(method, targetClass);
} /**
* 解析TransactionAttribute
*/
@Nullable
protected TransactionAttribute computeTransactionAttribute(Method method, @Nullable Class<?> targetClass) {
// 判断方法是否是public的
if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
return null;
} // 获取目标方法
Method specificMethod = AopUtils.getMostSpecificMethod(method, targetClass); // 在方法上查找事务属性的设置,findTransactionAttribute方法在AnnotationTransactionAttributeSource中实现
TransactionAttribute txAttr = findTransactionAttribute方法(specificMethod);
if (txAttr != null) {
return txAttr;
} // 在目标类上面查找事务属性的设置
txAttr = findTransactionAttribute(specificMethod.getDeclaringClass());
if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
return txAttr;
} if (specificMethod != method) {
// 使用方法上配置的事务属性
txAttr = findTransactionAttribute(method);
if (txAttr != null) {
return txAttr;
}
// 使用类上面配置的事务属性
txAttr = findTransactionAttribute(method.getDeclaringClass());
if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
return txAttr;
}
}
return null;
} }

总结

事务是基于AOP实现的,事务的Advisor是BeanFactoryTransactionAttributeSourceAdvisor,Advisor判断方法是否匹配时,是通过Pointcut的matches方法判断的,事务的Pointcut是TransactionAttributeSourcePointcut,里面实现了方法是否与事务切点匹配的判断:

  1. 对类的匹配是通过判断目标类是否是Transactional注解的候选类实现的,我们创建的类一般不会以java.开头,所以说可以与Transactional注解匹配成功。

  2. 对方法的匹配是通过解析方法上面配置的事务属性判断的,如果解析到了事务属性,则满足匹配条件。

TransactionInterceptor

TransactionInterceptor是事务Advisor的Advice,执行目标方法时,方法会被拦截,进入到TransactionInterceptor中,在TransactionInterceptor的invoke方法中实际是调用invokeWithinTransaction执行的:

public class TransactionInterceptor extends TransactionAspectSupport implements MethodInterceptor, Serializable {
@Override
@Nullable
public Object invoke(MethodInvocation invocation) throws Throwable {
Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null); // 通过事务执行目标方法,实现在TransactionAspectSupport方法中
return invokeWithinTransaction(invocation.getMethod(), targetClass, invocation::proceed);
}
}

TransactionAspectSupport

TransactionAspectSupport中实现了invokeWithinTransaction方法:

  1. 获取事务属性TransactionAttribute和TransactionManager事务管理器
  2. 对响应式事务、声明式事务和编程式事务分别进行判断,以声明式事务为例步骤如下:
    • 创建事务
    • 执行方法
    • 捕捉异常,如果抛出异常进行回滚
    • 清除事务信息
    • 提交事务
public abstract class TransactionAspectSupport implements BeanFactoryAware, InitializingBean {
@Nullable
protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass,
final InvocationCallback invocation) throws Throwable { // 获取TransactionAttributeSource
TransactionAttributeSource tas = getTransactionAttributeSource();
final TransactionAttribute txAttr = (tas != null ? tas.getTransactionAttribute(method, targetClass) : null);
// 获取事务管理器TransactionManager
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 {
// This is an around advice: Invoke the next interceptor in the chain.
// 这是一个环绕通知,将会在拦截链中执行下一个拦截
retVal = invocation.proceedWithInvocation();
}
catch (Throwable ex) {
// 捕捉异常,进行回滚
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;
}
}
}
}

总结

参考

【猫吻鱼】Spring源码分析:全集整理

Spring版本:5.2.5.RELEASE

【Srping】事务的执行原理(一)的更多相关文章

  1. 【Spring】事务的执行原理(二)

    前置知识 事务的执行步骤如下: 获取事务管理器 创建事务 执行目标方法 捕捉异常,如果出现异常进行回滚 提交事务 public abstract class TransactionAspectSupp ...

  2. 【Spring】事务的执行原理(三)

    事务的回滚 如果获取事务属性不为空,并且抛出的异常是RuntimeException或者Error类型,调用事务管理器中的rollback方法进行回滚 如果事务属性为空或者抛出的异常不是Runtime ...

  3. spring Mvc 执行原理 及 xml注解配置说明 (六)

    Spring MVC 执行原理 在 Spring Mvc 访问过程里,每个请求都首先经过 许多的过滤器,经 DispatcherServlet 处理; 一个Spring MVC工程里,可以配置多个的 ...

  4. Spring MVC执行原理

    spring的MVC执行原理 1.spring mvc将所有的请求都提交给DispatcherServlet,它会委托应用系统的其他模块负责对请求 进行真正的处理工作. 2.DispatcherSer ...

  5. spring的MVC执行原理

    spring的MVC执行原理 1.spring mvc将所有的请求都提交给DispatcherServlet,它会委托应用系统的其他模块负责对请求 进行真正的处理工作. 2.DispatcherSer ...

  6. PHP执行原理

    简单解释:PHP执行原理 客户端向服务器发送一个请求,如果请求的是一个HTML页面,服务器直接将HTML页面发送到客户端给浏览器解析,如果请求的是PHP页面,则服务器会运行PHP页面然后生成标准的HT ...

  7. TCC分布式事务的实现原理(转载 石杉的架构笔记)

    拜托,面试请不要再问我TCC分布式事务的实现原理![石杉的架构笔记] 原创: 中华石杉 目录 一.写在前面 二.业务场景介绍 三.进一步思考 四.落地实现TCC分布式事务 (1)TCC实现阶段一:Tr ...

  8. 【原创】Mysql中事务ACID实现原理

    引言 照例,我们先来一个场景~ 面试官:"知道事务的四大特性么?" 你:"懂,ACID嘛,原子性(Atomicity).一致性(Consistency).隔离性(Isol ...

  9. 拜托,面试请不要再问我TCC分布式事务的实现原理!(转)

    一.写在前面 之前网上看到很多写分布式事务的文章,不过大多都是将分布式事务各种技术方案简单介绍一下.很多朋友看了不少文章,还是不知道分布式事务到底怎么回事,在项目里到底如何使用. 所以咱们这篇文章,就 ...

随机推荐

  1. C#多线程下的调优

    一.原子操作 先看一段问题代码 /// <summary> /// 获取自增 /// </summary> public static void GetIncrement() ...

  2. C++---继承和派生

    继承和派生 在C++中, 代码重用是通过继承机制来实现的 继承, 就是在一个已经存在的类的基础上, 再建议一个新类 从已经有的类派生出新的类, 派生类就继承了基类的特征, 包括成员和方法 继承可以完成 ...

  3. int bool str

    一. python的基本数据类型 1. int 整数 2. bool 布尔.  判断.  if  while 3. str  字符串 ,一般存放小量的数据 4. list  列表. 可以存放大量的数据 ...

  4. 模拟FCFS调度算法(先来先服务)

    文章目录 一.FCFS的介绍 二.代码演示 三.代码分析 1.使用节点模拟进程 2.SimulateFCFS(核心模拟FCFS类) 3.创建一个节点为n的队列(模拟就绪队列) 4.核心计算分析 5.输 ...

  5. 推荐一个我写的Python库——PyNAS

    介绍 PyNAS是一个以Python的Updog的库为基础,制作而来的库 安装 pip安装(推荐) pip install PyNAS 源码安装(推荐) Github: git clone https ...

  6. events.js 源码分析

    events.js 源码分析 1. 初始化 // 使用 this.ee = new EventEmitter(); // 源码 // 绑定this域,初始化 _events,_eventsCount和 ...

  7. git 将本地文件推送到远程分支的分支

    1.  新建文件夹复制远程分支 2. 切换到远程分支 3. 推送到远程 添加到暂存区,先运行 " git add . " 查看文件状态                     在运 ...

  8. Persistent Bits - 题解【二进制】

    题面: WhatNext Software creates sequence generators that they hope will produce fairly random sequence ...

  9. C# 11 的这个新特性,我愿称之最强!

    前言 在日常开发中我们经常会将JSON.XML.HTML.SQL.Regex等字符串拷贝粘贴到我们的代码中,而这些字符串往往包含很多的引号",我们就必须将所有引号逐个添加转义符\进行转义.这 ...

  10. 如何改变函数内部 this 的指向

    一.函数内 this 的指向 1. this 的指向是当调用函数时确定的,调用的方式不同,this 的指向也就不同. 1.1 this 一般是指向调用者. 函数类型 this 的指向 普通函数 Win ...