Spring及Spring boot 第四章-第二节 Spring声明式事务管理 解析@Transactional
这个过程可以和@Aspect 实现的AOP来进行对比
SpringAop获取Advisor
(1) 获取Advisor——BeanFactoryTransactionAttributeSourceAdvisor
@Transactional和@Aspect获取Advisor的不同之处在于它的Advisor一开始便是以Bean的形式存在,不需要通过解析@Aspect注解来将方法转化为Advisor
(2)判断Advisor是否应用于该Bean
在Spring声明式事务管理解析@Transactional注解的过程中会将它的信息转化为TransactionAttribute对象,
首先进行判断,BeanFactoryTransactionAttributeSourceAdvisor不是IntroductionAdvisor类型然后开始判断canApply,这是重点
IntroductionAdvisor的意义是实现AOP引入功能,和切点功能还不太一样。这里BeanFactoryTransactionAttributeSourceAdvisor当然是作为PointCutAdvisor 参考链接跟着小马哥学系列之 Spring AOP
AopUtils#canApply——非常重要的场景
它做了两件事
1. 判断这个目标类上有没有@Transactional注解,这样就可以知道事务相关的Advisor(BeanFactoryTransactionAttributeSourceAdvisor)能不能应用于该Bean,方便做之后的处理
2. 如果有,之后就进行真正的@Transactional注解解析,这里是非常重要的点(获取TransactionDefinition)
public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
Assert.notNull(pc, "Pointcut must not be null");
if (!pc.getClassFilter().matches(targetClass)) {
return false;
} else {
MethodMatcher methodMatcher = pc.getMethodMatcher();
if (methodMatcher == MethodMatcher.TRUE) {
return true;
} else {
IntroductionAwareMethodMatcher introductionAwareMethodMatcher = null;
if (methodMatcher instanceof IntroductionAwareMethodMatcher) {
introductionAwareMethodMatcher = (IntroductionAwareMethodMatcher)methodMatcher;
}
Set<Class<?>> classes = new LinkedHashSet();
if (!Proxy.isProxyClass(targetClass)) {
classes.add(ClassUtils.getUserClass(targetClass));
}
classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));
Iterator var6 = classes.iterator();
while(var6.hasNext()) {
Class<?> clazz = (Class)var6.next();
Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
Method[] var9 = methods;
int var10 = methods.length;
for(int var11 = 0; var11 < var10; ++var11) {
Method method = var9[var11];
if (introductionAwareMethodMatcher != null) {
if (introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions)) {
return true;
}
} else if (methodMatcher.matches(method, targetClass)) {
return true;
}
}
}
return false;
}
}
}
2.1 粗筛 ——判断Bean类中有没有@Transactional注解
这步属于粗筛,一方面我们都知道@Transactional注解是可以加到方法或者类上的,粗筛会通过把这个类上的所有注解都遍历一下看有没有Transactional.Class类型的注解,只做这一件事,返回个true或者false,不属于真正对@Transactional的处理
TransactionAttributeSourceClassFilter#matches
这里就需要通过TransactionAttributeSource的实现类(AnnotationTransactionAttributeSource)来实现
AnnotationTransactionAttributeSource#isCandidateClass(clazz)
2.2 真正的筛选
重点 methodMatcher.matches(method, targetClass) 从附录中可以看到实现的就是TransactionAttributeSourcePointcut#matches
TransactionAttributeSourcePointcut#matches ——这里有最重要的一步,拿到通过tas拿到我们的BeanDefinition
一定要对命名有敏感,TransactionAttributeSource就是TransactionAttribute源,也就是说,所有的TransactionAttribute保存到TransactionAttributeSource相关的实现类中,TransactionAttribute就是我们事务功能实现中的TransactionDefinition组件。
缓存
不出意外拿到@Transactional注解 事务信息的话,这里就会返回true,整个获得Advisor的过程就成功结束
根据TransactionAttributeSource拿到@Transactional包装的所有事务信息
这个过程可以是从AbstractFallbackTransactionAttributeSource#getTransactionAttribute开始的,可以跳转查看
Spring及Spring boot 第四章-第二节 Spring声明式事务管理 AbstractFallbackTransactionAttributeSource
附录
解析@Transactional转变过程
Advisor——Pointcut
Pointcut——MethodMatcher
TransactionAttributeSourcePointcut实现的是父类StaticMethodMatcherPointcut的getMethodMatcher 其实就是返回TransactionAttributeSourcePointcut对象自己。
MethodMatcher(Pointcut本身)—— TransactionAttributeSource
|