作者简介:大家好,我是smart哥,前中兴通讯、美团架构师,现某互联网公司CTO
联系qq:184480602,加我进群,大家一起学习,一起进步,一起对抗互联网寒冬
学习必须往深处挖,挖的越深,基础越扎实!
阶段1、深入多线程
阶段2、深入多线程设计模式
阶段3、深入juc源码解析
码哥源码部分
码哥讲源码-原理源码篇【2024年最新大厂关于线程池使用的场景题】
码哥讲源码-原理源码篇【揭秘join方法的唤醒本质上决定于jvm的底层析构函数】
码哥源码-原理源码篇【Doug Lea为什么要将成员变量赋值给局部变量后再操作?】
码哥讲源码【谁再说Spring不支持多线程事务,你给我抽他!】
打脸系列【020-3小时讲解MESI协议和volatile之间的关系,那些将x86下的验证结果当作最终结果的水货们请闭嘴】
初始化流程图
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
:
好了,今天就到这里了,希望对学习理解有帮助,大神看见勿喷,仅为自己的学习理解,能力有限,请多包涵。
标签:return,Spring,method,txAttr,59AOP,targetClass,null,源码 From: https://blog.csdn.net/smart_an/article/details/136757076