在上一篇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。