- 初始化流程图
- AbstractAdvisorAutoProxyCreator的findAdvisorsThatCanApply
-
- AopUtils的findAdvisorsThatCanApply
-
- AopUtils的canApply
-
- AbstractFallbackTransactionAttributeSource的getTransactionAttribute
-
- AbstractFallbackTransactionAttributeSource的computeTransactionAttribute(获取事务属性的核心方法)
- AnnotationTransactionAttributeSource的findTransactionAttribute
初始化流程图
AbstractAdvisorAutoProxyCreator的findAdvisorsThatCanApply
前面BeanFactoryTransactionAttributeSourceAdvisor
已经被实例化了,现在要检测实例化之后的bean是否需要通知器,其实就是检测方法或者类上是否有事务注解。
AopUtils的findAdvisorsThatCanApply
主要是这里,看是否有事务注解:
AopUtils的canApply
主要是这个方法,他会获取目标类以及父类的所有的方法,进行一一匹配,查看方法和类上是否有事务注解,有的话就直接返回,说明这个类型是可以进行通知器应用的。
public static boolean canApply(Pointcut pc, Class<?> targetClass, boolean hasIntroductions) {
...
//存放要代理的类,以及他的接口
Set<Class<?>> classes = new LinkedHashSet<>();
if (!Proxy.isProxyClass(targetClass)) {
//不是JDK的代理类
classes.add(ClassUtils.getUserClass(targetClass));//实现类
}
classes.addAll(ClassUtils.getAllInterfacesForClassAsSet(targetClass));//获取所有接口,包括父类的
//循环遍历
for (Class<?> clazz : classes) {
Method[] methods = ReflectionUtils.getAllDeclaredMethods(clazz);
for (Method method : methods) {
//获取所有方法,包括父类的。只要有一个匹配上就返回
if (introductionAwareMethodMatcher != null ?
introductionAwareMethodMatcher.matches(method, targetClass, hasIntroductions) :
methodMatcher.matches(method, targetClass)) {
return true;
}
}
}
return false;
}
AbstractFallbackTransactionAttributeSource的getTransactionAttribute
最终matches
内部的是调用这个方法,首先会进行缓存的获取,因为类那么多,方法那么多,每次都解析一遍耗性能,所以进行了缓存,如果没有缓存就进行事务属性的获取,如果获取到就放入缓存并返回,否则就返回null
。
@Override
@Nullable
public TransactionAttribute getTransactionAttribute(Method method, @Nullable Class<?> targetClass) {
if (method.getDeclaringClass() == Object.class) {
return null;
}
//先看缓存
Object cacheKey = getCacheKey(method, targetClass);
TransactionAttribute cached = this.attributeCache.get(cacheKey);
if (cached != null) {
//有缓存,不会每次computeTransactionAttribute
if (cached == NULL_TRANSACTION_ATTRIBUTE) {
//如果没有事务属性的直接返回null
return null;
}
else {
return cached;//存在就直接返回事务属性
}
}
else {
// 获取事务属性
TransactionAttribute txAttr = computeTransactionAttribute(method, targetClass);
if (txAttr == null) {
this.attributeCache.put(cacheKey, NULL_TRANSACTION_ATTRIBUTE);
}
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;
}
}
AbstractFallbackTransactionAttributeSource的computeTransactionAttribute(获取事务属性的核心方法)
这个方法首先会判断方法是否是public
,默认是只支持public
的。
然后会进行方法的获取,我们考虑一般情况,获取的specificMethod
就是method
,然后优先specificMethod
方法上解析的事务注解的属性,会去找父类或者接口的方法,找不到的话再尝试声明该方法的类上的注解属性,会去父类或者接口找。如果specificMethod != method
,就到method
上去找。
@Nullable
protected TransactionAttribute computeTransactionAttribute(Method method, @Nullable Class<?> targetClass) {
if (allowPublicMethodsOnly() && !Modifier.isPublic(method.getModifiers())) {
return null;//只支持public方法
}
Method specificMethod = AopUtils.getMostSpecificMethod(method, targetClass);
//优先方法上解析的事务注解的属性,会去找父类或者接口的方法
TransactionAttribute txAttr = findTransactionAttribute(specificMethod);
if (txAttr != null) {
return txAttr;
}
//如果没有,再尝试声明该方法的类上的注解属性,会去父类或者接口找
txAttr = findTransactionAttribute(specificMethod.getDeclaringClass());
if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
return txAttr;
}
//如果指定方法不等于方法
if (specificMethod != method) {
// Fallback is to look at the original method.
txAttr = findTransactionAttribute(method);//找方法上的
if (txAttr != null) {
return txAttr;
}
txAttr = findTransactionAttribute(method.getDeclaringClass());//method方法的类上的
if (txAttr != null && ClassUtils.isUserLevelMethod(method)) {
return txAttr;
}
}
return null;
}
AnnotationTransactionAttributeSource的findTransactionAttribute
其实内部就是去寻找Transactional
注解的属性,而且会对父类和接口也寻找,因为事务注解可以在类和方法上。
然后是这里:
至此事务注解属性获取差不多了,其实就是将有Transactional
注解方法放入AnnotationTransactionAttributeSource
的缓存attributeCache
中,下次可以直接拿出来用,当然里面没有Transactional
注解的都是null
,有的才是注解属性TransactionAttribute
:
好了,今天就到这里了,希望对学习理解有帮助,大神看见勿喷,仅为自己的学习理解,能力有限,请多包涵。