MatchAlwaysTransactionAttributeSource
它是TransactionAttributeSource的一个最简单的实现,每次调用,都是返回相同的TransactionAttribute
当然它是可议set一个TransactionAttribute作为通用的事务属性的实现的
AnnotationTransactionAttributeSource
这个就是重点了,它是基于注解驱动的事务管理的事务属性源,和@Transaction相关,也是现在使用得最最多的方式。
它的基本作用为:它遇上比如@Transaction标注的方法时,此类会分析此事务注解,最终组织形成一个TransactionAttribute供随后的调用。
public class AnnotationTransactionAttributeSource extends AbstractFallbackTransactionAttributeSource implements Serializable { // 这个是“向下兼容”,JavaEE提供的其余两种注解~~ private static final boolean jta12Present; //JTA 1.2事务注解 private static final boolean ejb3Present; //EJB 3 事务注解是 static { ClassLoader classLoader = AnnotationTransactionAttributeSource.class.getClassLoader(); jta12Present = ClassUtils.isPresent("javax.transaction.Transactional", classLoader); ejb3Present = ClassUtils.isPresent("javax.ejb.TransactionAttribute", classLoader); } // true:只处理public方法(基于JDK的代理 显然就只会处理这种方法) // false:private/protected等方法都会处理。 基于AspectJ代理得方式可议设置为false // 默认情况下:会被赋值为true,表示只处理public的方法 private final boolean publicMethodsOnly; // 保存用于分析事务注解的事务注解分析器 这个注解分析的解析器是重点 private final Set<TransactionAnnotationParser> annotationParsers; // 构造函数, publicMethodsOnly 缺省使用 true public AnnotationTransactionAttributeSource() { this(true); } public AnnotationTransactionAttributeSource(boolean publicMethodsOnly) { this.publicMethodsOnly = publicMethodsOnly; 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()); } } // 默认情况下,只添加Spring自己的注解解析器(绝大部分情况都实这里) else { this.annotationParsers = Collections.singleton(new SpringTransactionAnnotationParser()); } } // 自己也可以指定一个TransactionAnnotationParser 或者多个也成 public AnnotationTransactionAttributeSource(TransactionAnnotationParser annotationParser) { ... } public AnnotationTransactionAttributeSource(TransactionAnnotationParser... annotationParsers) { ... } public AnnotationTransactionAttributeSource(Set<TransactionAnnotationParser> annotationParsers) { ... } // 获取某个类/方法上的事务注解属性(属于 父类的抽象方法) @Override @Nullable protected TransactionAttribute findTransactionAttribute(Class<?> clazz) { return determineTransactionAttribute(clazz); } @Override @Nullable protected TransactionAttribute findTransactionAttribute(Method method) { return determineTransactionAttribute(method); } // 具体实现如下: // 分析获取某个被注解的元素(AnnotatedElement ),具体的来讲,指的是一个类或者一个方法上的事务注解属性。 // 实现会遍历自己属性annotationParsers中所包含的事务注解属性分析器试图获取事务注解属性 所以主要还是依赖于TransactionAnnotationParser 去解析的 @Nullable protected TransactionAttribute determineTransactionAttribute(AnnotatedElement element) { 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; } ... }
从源码中可议知道,真正提供给调用的getTransactionAttribute在父类中实现的:
AbstractFallbackTransactionAttributeSource
AbstractFallbackTransactionAttributeSource是接口TransactionAttributeSource的抽象实现,也是上面提到的工具类AnnotationTransactionAttributeSource的父类。
public abstract class AbstractFallbackTransactionAttributeSource implements TransactionAttributeSource { // 针对没有事务注解属性的方法进行事务注解属性缓存时使用的特殊值,用于标记该方法没有事务注解属性 // 从而不用在首次缓存在信息后,不用再次重复执行真正的分析 来提高查找的效率 // 标注了@Transaction注解的表示有事务属性的,才会最终加入事务。但是,但是此处需要注意的是,只要被事务的Advisor切中的,都会缓存起来 放置过度的查找~~~~ 因此才有这个常量的出现 private static final TransactionAttribute NULL_TRANSACTION_ATTRIBUTE = new DefaultTransactionAttribute() { @Override public String toString() { return "null"; } }; // 方法上的事务注解属性缓存,key使用目标类上的方法,使用类型MethodClassKey来表示 // 这个Map会比较大,会被事务相关的Advisor拦截下来的方法,最终都会缓存下来。关于事务相关的Advisor,后续也是会着重讲解的~~~ // 因为会有很多,所以我们才需要一个NULL_TRANSACTION_ATTRIBUTE常量来提高查找的效率~~~ private final Map<Object, TransactionAttribute> attributeCache = new ConcurrentHashMap<>(1024); // 获取指定方法上的注解事务属性 如果方法上没有注解事务属性,则使用目标方法所属类上的注解事务属性 @Override @Nullable public TransactionAttribute getTransactionAttribute(Method method, @Nullable Class<?> targetClass) { // 如果目标方法是内置类Object上的方法,总是返回null,这些方法上不应用事务 if (method.getDeclaringClass() == Object.class) { return null; } // 先看缓存里有木有,此处使用的非常经典的MethodClassKey作为Map的key Object cacheKey = getCacheKey(method, targetClass); TransactionAttribute cached = this.attributeCache.get(cacheKey); if (cached != null) { //目标方法上上并没有事务注解属性,但是已经被尝试分析过并且已经被缓存, // 使用的值是 NULL_TRANSACTION_ATTRIBUTE,所以这里再次尝试获取其注解事务属性时,直接返回 null if (cached == NULL_TRANSACTION_ATTRIBUTE) { return null; } else { return cached; } } // 缓存没有命中~~~~ else { // 通过方法、目标Class 分析出此方法上的事务属性~~~~~ TransactionAttribute txAttr = computeTransactionAttribute(method, targetClass); // 如果目标方法上并没有使用注解事务属性,也缓存该信息,只不过使用的值是一个特殊值: if (txAttr == null) { this.attributeCache.put(cacheKey, NULL_TRANSACTION_ATTRIBUTE); } // 存在目标属性~ 就put到里面去。 // 获取到methodIdentification 基本只为了输出日志~~~ else { String methodIdentification = ClassUtils.getQualifiedMethodName(method, targetClass); 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; } } //查找目标方法上的事务注解属性 也是上面的核心方法 @Nullable protected TransactionAttribute computeTransactionAttribute(Method method, @Nullable Class<?> targetClass) { // 如果事务注解属性分析仅仅针对public方法,而当前方法不是public,则直接返回null // 如果是private,AOP是能切入,代理对象也会生成的 但就是事务不回生效的~~~~ if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) { return null; } // 上面说了,因为Method并不一样属于目标类。所以这个方法就是获取targetClass上的那个和method对应的方法 也就是最终要执行的方法 Method specificMethod = AopUtils.getMostSpecificMethod(method, targetClass); // 第一步:去找直接标记在方法上的事务属性~~~ 如果方法上有就直接返回(不用再看类上的了) // findTransactionAttribute这个方法其实就是子类去实现的 TransactionAttribute txAttr = findTransactionAttribute(specificMethod); if (txAttr != null) { return txAttr; } // 然后尝试检查事务注解属性是否标记在目标方法 specificMethod(注意此处用不是Method) 所属类上 txAttr = findTransactionAttribute(specificMethod.getDeclaringClass()); if (txAttr != null && ClassUtils.isUserLevelMethod(method)) { return txAttr; } // 程序走到这里说明目标方法specificMethod,也就是实现类上的目标方法上没有标记事务注解属性(否则直接返回了嘛) // 如果 specificMethod 和 method 不同,则说明 specificMethod 是具体实现类的方法method 是实现类所实现接口的方法 // 因此再次尝试从 method 上获取事务注解属性 // 这也就是为何我们的@Transaction标注在接口上或者接口的方法上都是好使的原因~~~~~~~ if (specificMethod != method) { // Fallback is to look at the original method. txAttr = findTransactionAttribute(method); if (txAttr != null) { return txAttr; } txAttr = findTransactionAttribute(method.getDeclaringClass()); if (txAttr != null && ClassUtils.isUserLevelMethod(method)) { return txAttr; } } return null; } // 可议看到默认值是false 表示private的也是ok的 // 但是`AnnotationTransactionAttributeSource`复写了它 可以由开发者指定(默认是true了) protected boolean allowPublicMethodsOnly() { return false; } }