概述
这是一个TransactionAttributeSource
接口的实现类,用于从类或者方法上事务注解分析相应的事务属性。它读取Spring
的注解@Transactional
,JTA 1.2+
注解@Transactional
(位于包javax.transaction
),或者EJB 3
的注解@TransactionAttribute
(位于包javax.ejb
),得到相应的事务属性给调用者使用。该工具类并不是设计给应用开发人员的,是一个Spring
框架内部使用的工具。
该类也可以充当自定义TransactionAttributeSource
的基类,或者通过TransactionAnnotationParser
策略机制进行定制。
关于应用
1. 引入
配置类ProxyTransactionManagementConfiguration
定义了一个实际类型为AnnotationTransactionAttributeSource
的bean
,并将该bean
传递给另外一个TransactionInterceptor bean
作为获取事务注解属性的工具使用 :
// ProxyTransactionManagementConfiguration 代码片段
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public TransactionAttributeSource transactionAttributeSource() {
return new AnnotationTransactionAttributeSource();
}
@Bean
@Role(BeanDefinition.ROLE_INFRASTRUCTURE)
public TransactionInterceptor transactionInterceptor() {
TransactionInterceptor interceptor = new TransactionInterceptor();
interceptor.setTransactionAttributeSource(transactionAttributeSource());
if (this.txManager != null) {
interceptor.setTransactionManager(this.txManager);
}
return interceptor;
}
- 该配置类
ProxyTransactionManagementConfiguration
会被TransactionManagementConfigurationSelector
导入; TransactionManagementConfigurationSelector
会被注解@EnableTransactionManagement
导入;- 而对于一个
Spring Boot
应用,注解@EnableTransactionManagement
会被自动配置类TransactionAutoConfiguration
使用。
2. 使用
// TransactionAspectSupport 代码片段,
@Nullable
protected Object invokeWithinTransaction(Method method, @Nullable Class<?> targetClass,
final InvocationCallback invocation) throws Throwable {
// If the transaction attribute is null, the method is non-transactional.
// 这里的 tas ,在 Spring Boot 应用中,缺省就是 ProxyTransactionManagementConfiguration 中定义的
// AnnotationTransactionAttributeSource bean
TransactionAttributeSource tas = getTransactionAttributeSource();
// 从方法上分析事务注解从而获取事务属性
final TransactionAttribute txAttr = (tas != null ?
tas.getTransactionAttribute(method, targetClass) : null);
// ... 省略其他代码
}
源代码解析
源代码版本 :
spring-tx-5.1.5.RELEASE
package org.springframework.transaction.annotation;
// 忽略 import 行
@SuppressWarnings("serial")
public class AnnotationTransactionAttributeSource extends AbstractFallbackTransactionAttributeSource
implements Serializable {
// 用于记录 JTA 1.2 是否被使用
private static final boolean jta12Present;
// 用于记录 EJB 3 是否被使用
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);
}
// 是否仅仅针对使用事务注解的 public 方法,而不针对 protected/private 方法
// 缺省情况下初始值为 true
private final boolean publicMethodsOnly;
// 保存将要使用的事务注解解析器
private final Set<TransactionAnnotationParser> annotationParsers;
/**
* Create a default AnnotationTransactionAttributeSource, supporting
* public methods that carry the {@code Transactional} annotation
* or the EJB3 {@link javax.ejb.TransactionAttribute} annotation.
*/
public AnnotationTransactionAttributeSource() {
this(true);
}
/**
* Create a custom AnnotationTransactionAttributeSource, supporting
* public methods that carry the {@code Transactional} annotation
* or the EJB3 {@link javax.ejb.TransactionAttribute} annotation.
* @param publicMethodsOnly whether to support public methods that carry
* the {@code Transactional} annotation only (typically for use
* with proxy-based AOP), or protected/private methods as well
* (typically used with AspectJ class weaving)
*/
public AnnotationTransactionAttributeSource(boolean publicMethodsOnly) {
this.publicMethodsOnly = publicMethodsOnly;
// 1. 总是添加 Spring 自身的事务属性解析器;
// 2. 根据 JTA, EJB 包引入的情况决定是否要添加针对它们的事务属性解析器
if (jta12Present || ejb3Present) {
this.annotationParsers = new LinkedHashSet<>(4);
this.annotationParsers.add(new SpringTransactionAnnotationParser());
if (jta12Present) {
this.annotationParsers.add(new JtaTransactionAnnotationParser());
}
if (ejb3Present) {
this.annotationParsers.add(new Ejb3TransactionAnnotationParser());
}
}
else {
this.annotationParsers = Collections.singleton(new SpringTransactionAnnotationParser());
}
}
/**
* Create a custom AnnotationTransactionAttributeSource.
* @param annotationParser the TransactionAnnotationParser to use
*/
public AnnotationTransactionAttributeSource(TransactionAnnotationParser annotationParser) {
this.publicMethodsOnly = true;
Assert.notNull(annotationParser, "TransactionAnnotationParser must not be null");
this.annotationParsers = Collections.singleton(annotationParser);
}
/**
* Create a custom AnnotationTransactionAttributeSource.
* @param annotationParsers the TransactionAnnotationParsers to use
*/
public AnnotationTransactionAttributeSource(TransactionAnnotationParser... annotationParsers) {
this.publicMethodsOnly = true;
Assert.notEmpty(annotationParsers, "At least one TransactionAnnotationParser needs to be specified");
this.annotationParsers = new LinkedHashSet<>(Arrays.asList(annotationParsers));
}
/**
* Create a custom AnnotationTransactionAttributeSource.
* @param annotationParsers the TransactionAnnotationParsers to use
*/
public AnnotationTransactionAttributeSource(Set<TransactionAnnotationParser> annotationParsers) {
this.publicMethodsOnly = true;
Assert.notEmpty(annotationParsers, "At least one TransactionAnnotationParser needs to be specified");
this.annotationParsers = annotationParsers;
}
@Override
@Nullable
protected TransactionAttribute findTransactionAttribute(Class<?> clazz) {
return determineTransactionAttribute(clazz);
}
@Override
@Nullable
protected TransactionAttribute findTransactionAttribute(Method method) {
return determineTransactionAttribute(method);
}
/**
* Determine the transaction attribute for the given method or class.
* <p>This implementation delegates to configured
* {@link TransactionAnnotationParser TransactionAnnotationParsers}
* for parsing known annotations into Spring's metadata attribute class.
* Returns {@code null} if it's not transactional.
* <p>Can be overridden to support custom annotations that carry transaction metadata.
* @param element the annotated method or class
* @return the configured transaction attribute, or {@code null} if none was found
*/
@Nullable
protected TransactionAttribute determineTransactionAttribute(AnnotatedElement element) {
// element 可以是个方法,也可以是个类
// 遍历所指定的 annotationParsers ,尝试使用其中每一个从 element 上根据注解提取出
// 事务属性到 attr,遇到第一个成功的立即结束
for (TransactionAnnotationParser annotationParser : this.annotationParsers) {
TransactionAttribute attr = annotationParser.parseTransactionAnnotation(element);
if (attr != null) {
return attr;
}
}
// 该方法上没有能处理的事务属性注解
return null;
}
/**
* By default, only public methods can be made transactional.
*/
@Override
protected boolean allowPublicMethodsOnly() {
return this.publicMethodsOnly;
}
@Override
public boolean equals(Object other) {
if (this == other) {
return true;
}
if (!(other instanceof AnnotationTransactionAttributeSource)) {
return false;
}
AnnotationTransactionAttributeSource otherTas = (AnnotationTransactionAttributeSource) other;
return (this.annotationParsers.equals(otherTas.annotationParsers) &&
this.publicMethodsOnly == otherTas.publicMethodsOnly);
}
@Override
public int hashCode() {
return this.annotationParsers.hashCode();
}
}