2023-09-16
原文作者:王伟王胖胖 原文地址: https://blog.csdn.net/wangwei19871103/article/details/105328000

初始化流程图

202309162318357741.png

AbstractAdvisorAutoProxyCreator的findAdvisorsThatCanApply

前面BeanFactoryTransactionAttributeSourceAdvisor已经被实例化了,现在要检测实例化之后的bean是否需要通知器,其实就是检测方法或者类上是否有事务注解。

202309162318364502.png

AopUtils的findAdvisorsThatCanApply

主要是这里,看是否有事务注解:

202309162318369293.png

AopUtils的canApply

202309162318376654.png
主要是这个方法,他会获取目标类以及父类的所有的方法,进行一一匹配,查看方法和类上是否有事务注解,有的话就直接返回,说明这个类型是可以进行通知器应用的。

    	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的。

202309162318383525.png
然后会进行方法的获取,我们考虑一般情况,获取的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注解的属性,而且会对父类和接口也寻找,因为事务注解可以在类和方法上。

202309162318387236.png
然后是这里:

202309162318391047.png

202309162318395998.png
至此事务注解属性获取差不多了,其实就是将有Transactional注解方法放入AnnotationTransactionAttributeSource的缓存attributeCache中,下次可以直接拿出来用,当然里面没有Transactional注解的都是null,有的才是注解属性TransactionAttribute

202309162318401119.png

2023091623184071510.png

好了,今天就到这里了,希望对学习理解有帮助,大神看见勿喷,仅为自己的学习理解,能力有限,请多包涵。

阅读全文