在使用事务的时候需要添加@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. 集成JUnit测试

    集成JUnit测试 既然使用了Spring,那么怎么集成到JUnit中进行测试呢,首先大家能够想到的肯定是: public class TestMain { @Test public void tes ...

  2. mysql-cluster-gpl-7.5.10-linux-glibc2.12-x86_64.tar.gz (有必要解释一下)

    大部分软件我们接触的时候会发现,起的名称有点怪异,所以我觉得有必要解释一下. 比如: mysql-cluster-gpl-7.5.10-linux-glibc2.12-x86_64.tar.gz 名称 ...

  3. OpenHarmony标准设备应用开发(一)——HelloWorld

    (以下内容来自开发者分享,不代表 OpenHarmony 项目群工作委员会观点) 邢碌 本文是 OpenAtom OpenHarmony(以下简称"OpenHarmony")标准设 ...

  4. 新手入门C语言第九章:C函数

    C 函数 函数是一组一起执行一个任务的语句.每个 C 程序都至少有一个函数,即主函数 main() ,所有简单的程序都可以定义其他额外的函数.您可以把代码划分到不同的函数中.如何划分代码到不同的函数中 ...

  5. Caused by: com.sonatype.nexus.staging.client.StagingRuleFailuresException: Staging rules failure! 已解决!

    问题分析 由于项目中修改了一些代码,然后没有修改版本号,直接deploy代码到仓库,最终导致错误! 根据 https://central.sonatype.org/faq/can-i-change-a ...

  6. 论文解读(BGRL)《Bootstrapped Representation Learning on Graphs》

    论文信息 论文标题:Bootstrapped Representation Learning on Graphs论文作者:Shantanu Thakoor, Corentin Tallec, Moha ...

  7. 2021.08.10 Euler函数总结

    2021.08.10 Euler函数总结 知识: 记 φ(n) 表示在 [1,n] 中与 n互质的数的个数. 1.p为质数,则 \[φ(p^l)=p^l-p=p^{l-1}(p-1) \] 注:每p个 ...

  8. Attention Mechanism in Computer Vision

    ​  前言 本文系统全面地介绍了Attention机制的不同类别,介绍了每个类别的原理.优缺点. 欢迎关注公众号CV技术指南,专注于计算机视觉的技术总结.最新技术跟踪.经典论文解读.CV招聘信息. 概 ...

  9. XCTF练习题---MISC---simple_transfer

    XCTF练习题---MISC---simple_transfer flag:HITB{b3d0e380e9c39352c667307d010775ca} 解题步骤: 1.观察题目,下载附件 2.经过观 ...

  10. k8s入门之ConfigMap(九)

    ConfigMap是k8s的配置管理工具,通常用来保存明文的配置信息,以key-value形式传递配置. 一.使用命令创建ConfigMap对象 1.通过--from-literal参数创建 kube ...