文章目录
inherit
可以看到上图中有两个AbstractFallbackTransactionAttributeSource,其中上面那个是在spring-tx模块,其子类AnnotationTransactionAttributeSource正是我们最常用的处理 @Transactional的实现类,而下面的极其子类都是spring-data-commons里TransactionalRepositoryProxyPostProcessor的内部类,其代码和上面两个很类似。
AbstractFallbackTransactionAttributeSource
两个AbstractFallbackTransactionAttributeSource的代码是类似的,都是有以下两个方法完成业务逻辑,spring-data-commons里的更复杂以下。下面说下两个方法:
getTransactionAttribute
这个方法主要是起到缓存的作用,当缓存未命中的时候调用下面的方法得到TransactionAttribute并放入缓存。另外当Method是Object自带的方法的时候(显然没有事务)直接返回null
computeTransactionAttribute
这个方法尝试各种方法去寻找配置信息,从实现类到接口,从方法到类,尝试了2X2共4个地方去寻找信息。但是怎么读取信息,也就是
findTransactionAttribute却是抽象方法,交给子类处理。这里也回答了SpringBoot中的Transaction研究(四)Transactional中没有回答的问题,就是有四个地方都有注解的时候优先采用哪个?答案是SpecificMethod > SpecificMethod.getDeclaringClass > method > method.getDeclaringClass
findTransactionAttribute
在父类中这两个是抽象方法,两个子类各自都实现了这两个方法,实现方法也都一样,都是交给了determineTransactionAttribute来处理,具体的处理逻辑参见SpringBoot中的Transaction研究(四)Transactional
CompositeTransactionAttributeSource
这是一个集合代理类,其构造方法要求传入一些实现,然后在被调用的时候循环调用那些实现直到获得满意结果
MatchAlwaysTransactionAttributeSource
这是逻辑最为简单的实现类,代码如下
@Override
@Nullable
public TransactionAttribute getTransactionAttribute(Method method, @Nullable Class<?> targetClass) {
return (ClassUtils.isUserLevelMethod(method) ? this.transactionAttribute : null);
}
就是针对所有情况都使用预设的事务配置来处理。
MethodMapTransactionAttributeSource
这个实现类的业务逻辑也比较简单,其要义就是下面一句代码
@Override
@Nullable
public TransactionAttribute getTransactionAttribute(Method method, @Nullable Class<?> targetClass) {
//some code
return this.transactionAttributeMap.get(method);
}
}
就是在其内部维护了一个Map来根据每个Method来决定TransactionAttribute
NameMatchTransactionAttributeSource
相对于上面两个,这个实现类相对于复杂一些,它是通过方法名的匹配来(可以采用通配符)来寻找TransactionAttribute ,当有多个时使用最长的那一个,代码如下
@Override
@Nullable
public TransactionAttribute getTransactionAttribute(Method method, @Nullable Class<?> targetClass) {
if (!ClassUtils.isUserLevelMethod(method)) {
return null;
}
// Look for direct name match.
String methodName = method.getName();
TransactionAttribute attr = this.nameMap.get(methodName);
if (attr == null) {
// Look for most specific name match.
String bestNameMatch = null;
for (String mappedName : this.nameMap.keySet()) {
if (isMatch(methodName, mappedName) &&
(bestNameMatch == null || bestNameMatch.length() <= mappedName.length())) {
attr = this.nameMap.get(mappedName);
bestNameMatch = mappedName;
}
}
}
return attr;
}
我觉得这里有优化的空间,可以把nameMap的key按长度排序,这样当匹配成功是就可以直接return了,不用遍历所有的key
which
总的来看Spring提供了四个实现类那么到底用的是哪个呢?搜索getTransactionAttribute这个方法发现只有一处外部调用(排除CompositeTransactionAttributeSource的调用),那就是TransactionAspectSupport,并且发现NameMatchTransactionAttributeSource和CompositeTransactionAttributeSource都是出现在里面,里面有多个方法设置了transactionAttributeSource,
那么会调用TransactionAspectSupport哪一个方法呢?进一步观察发现这些方法都是通过TransactionProxyFactoryBean调用过来,其实TransactionAspectSupport只是转手而已,而FactoryBean的stter方法应该是通过容器反射调用,查找不到相关代码。
不过通过观察TransactionAspectSupport这个类只有一个子类TransactionInterceptor,并且只有一个地方调用了它的构造方法,那就是ProxyTransactionManagementConfiguration的transactionInterceptor方法,并且这个方法有**@Bean**标识,其入参要求一个TransactionAttributeSource,并且这个参数紧接着就设置进了TransactionInterceptor。下面挨在一起的两个方法应该可以回答到底是哪个实现类被选中了。
@Configuration(proxyBeanMethods = false)
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public class ProxyTransactionManagementConfiguration extends AbstractTransactionManagementConfiguration {
//some code
@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;
}
}