spring注解开发(五、AOP通知方法执行顺序原理)

       在上一篇spring注解开发(四、AOP之目标方法的执行过程)中,我们知道CglibMethodInvocation在执行拦截器链时,是递归执行已经排好序的通知方法,但是spring怎样知道那个通知方法的执行时机?

CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();

一、准备

       虽然我们都知道它的执行时机:

(1)前置通知

(2)目标方法

(3)后置通知

(4)返回通知或异常通知

     但是,我比较好奇,spring的内部是怎样判断的,最后发现spring:

        根据注解的不同,使用不同的Advisor来进行封装(具体如何,还没细看),下图是Advisor的通知方法的默认实现类的继承关系,从中可以看到,它实现了Ordered接口,这也就解释了,为什么这些通知方法可以排序了

二、如何排序?

    既然是实现了Ordered接口,自然要用上它的。

    先打断点定位到AbstractAutoProxyCreator的postProcessAfterInitialization():

	public Object postProcessAfterInitialization(@Nullable Object bean, String beanName) {
		if (bean != null) {
			Object cacheKey = getCacheKey(bean.getClass(), beanName);
			if (this.earlyProxyReferences.remove(cacheKey) != bean) {
				return wrapIfNecessary(bean, beanName, cacheKey);
			}
		}
		return bean;
	}

重点看这行代码:return wrapIfNecessary(bean, beanName, cacheKey);

跟进去几部,会发现这样一个方法:

	protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
		//查找所有的增强器
        List<Advisor> candidateAdvisors = findCandidateAdvisors();
        //选出可以应用在当前bean的增强器
		List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
        //拓展可以应用在当前bean的增强器
		extendAdvisors(eligibleAdvisors);
		if (!eligibleAdvisors.isEmpty()) {
            //对增强器进行排序
			eligibleAdvisors = sortAdvisors(eligibleAdvisors);
		}
		return eligibleAdvisors;
	}

根据方法名字可以推测,排序发生在这一行:

//对增强器进行排序
eligibleAdvisors = sortAdvisors(eligibleAdvisors);

跟进去,是这样一个方法:

	protected List<Advisor> sortAdvisors(List<Advisor> advisors) {
		List<PartiallyComparableAdvisorHolder> partiallyComparableAdvisors = new ArrayList<>(advisors.size());
		for (Advisor element : advisors) {
			partiallyComparableAdvisors.add(
					new PartiallyComparableAdvisorHolder(element, DEFAULT_PRECEDENCE_COMPARATOR));
		}
		List<PartiallyComparableAdvisorHolder> sorted = PartialOrder.sort(partiallyComparableAdvisors);
		if (sorted != null) {
			List<Advisor> result = new ArrayList<>(advisors.size());
			for (PartiallyComparableAdvisorHolder pcAdvisor : sorted) {
				result.add(pcAdvisor.getAdvisor());
			}
			return result;
		}
		else {
			return super.sortAdvisors(advisors);
		}
	}

发现它会将Advisor封装成PartiallyComparableAdvisorHolder,然后利用PartialOrder.sort()方法进行排序,那么我们的关注点,就是PartialOrder.sort()这个方法了,跟进去几步后,发现如下方法:

		public int compareTo(Object obj) {
			Advisor otherAdvisor = ((PartiallyComparableAdvisorHolder) obj).advisor;
			return this.comparator.compare(this.advisor, otherAdvisor);
		}

转了一圈,又回到了Advisor!最终通过comparator.compare()方法来比较,再进去就是两个Advisor的比较了:

	public int compare(Advisor o1, Advisor o2) {
		int advisorPrecedence = this.advisorComparator.compare(o1, o2);
		if (advisorPrecedence == SAME_PRECEDENCE && declaredInSameAspect(o1, o2)) {
			advisorPrecedence = comparePrecedenceWithinAspect(o1, o2);
		}
		return advisorPrecedence;
	}

关注点到了这一行代码:int advisorPrecedence = this.advisorComparator.compare(o1, o2);而它调用的是doCompare():

	private int doCompare(@Nullable Object o1, @Nullable Object o2, @Nullable OrderSourceProvider sourceProvider) {
       //判断是否实现了PriorityOrdered接口,实现了则排在前面
		boolean p1 = (o1 instanceof PriorityOrdered);
		boolean p2 = (o2 instanceof PriorityOrdered);
		if (p1 && !p2) {
			return -1;
		}
		else if (p2 && !p1) {
			return 1;
		}

        //如果两个对象都没有实现PriorityOrdered接口
		int i1 = getOrder(o1, sourceProvider);
		int i2 = getOrder(o2, sourceProvider);
		return Integer.compare(i1, i2);
	}

所以,重点落在了getOrder()这个方法,点进去,看一下:

	protected int getOrder(@Nullable Object obj) {
		if (obj != null) {
            //查找顺序
			Integer order = findOrder(obj);
			if (order != null) {
				return order;
			}
		}
        //如果对象为null,则返回排在在最后
		return Ordered.LOWEST_PRECEDENCE;
	}

那么,关注点就是findOrder()方法了,再进去看一下,发现是调用了其父类的方法:

	protected Integer findOrder(Object obj) {
		return (obj instanceof Ordered ? ((Ordered) obj).getOrder() : null);
	}

意思也很明确了,如果实现了Ordered接口,则直接返回它的顺序,否则返回null。

 

 

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值