SpringBoot中的Transaction研究(五)TransactionAttributeSource

inherit

TransactionAttributeSource
可以看到上图中有两个AbstractFallbackTransactionAttributeSource,其中上面那个是在spring-tx模块,其子类AnnotationTransactionAttributeSource正是我们最常用的处理 @Transactional的实现类,而下面的极其子类都是spring-data-commonsTransactionalRepositoryProxyPostProcessor的内部类,其代码和上面两个很类似。

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

这是一个集合代理类,其构造方法要求传入一些实现,然后在被调用的时候循环调用那些实现直到获得满意结果
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,并且发现NameMatchTransactionAttributeSourceCompositeTransactionAttributeSource都是出现在里面,里面有多个方法设置了transactionAttributeSource
那么会调用TransactionAspectSupport哪一个方法呢?进一步观察发现这些方法都是通过TransactionProxyFactoryBean调用过来,其实TransactionAspectSupport只是转手而已,而FactoryBean的stter方法应该是通过容器反射调用,查找不到相关代码。
不过通过观察TransactionAspectSupport这个类只有一个子类TransactionInterceptor,并且只有一个地方调用了它的构造方法,那就是ProxyTransactionManagementConfigurationtransactionInterceptor方法,并且这个方法有**@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;
	}

}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在 Spring Boot ,@Transactional 注解用于启用事务管理。它可以应用于类级别和方法级别。当它被应用在一个类上时,它将被应用于类的所有方法。当它被应用在方法级别时,它仅应用于该方法。以下是@ Transactional 注解的用法: 在类级别使用 @Transactional 注解: ``` @Service @Transactional public class UserServiceImpl implements UserService { // code } ``` 在方法级别使用 @Transactional 注解: ``` @Service public class UserServiceImpl implements UserService { @Override @Transactional public void saveUser(User user) { // code } } ``` 在方法级别使用 @Transactional 注解时,可以使用 propagation 属性来指定事务传播行为。例如,以下是一个示例: ``` @Service public class UserServiceImpl implements UserService { @Override @Transactional(propagation = Propagation.REQUIRED) public void saveUser(User user) { // code } } ``` 在上述示例,我们将 propagation 属性设置为 REQUIRED,它指示 Spring 在当前事务不存在时创建一个新事务,并在当前事务存在时使用当前事务。 @ Transactional 注解还有其他属性,例如 isolation、readOnly、timeout 等。这些属性用于控制事务的隔离级别、只读事务和超时。例如,以下是一个示例: ``` @Service public class UserServiceImpl implements UserService { @Override @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, readOnly = false, timeout = 10) public void saveUser(User user) { // code } } ``` 在上述示例,我们将 isolation 属性设置为 DEFAULT,它指示 Spring 使用默认的事务隔离级别。我们将 readOnly 属性设置为 false,它指示 Spring 在事务允许写操作。我们将 timeout 属性设置为 10,它指示 Spring 在 10 秒后将事务超时。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值