58、Spring5.x源码之旅五十九AOP事务的初始化流程二

  • 初始化流程图
  • 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
*
*

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