spring源碼分析——aop切面順序實現原理

使用spring版本爲4.3.22

1. 簡介

對於同一個目標方法而言,切面觸發的順序如下:

Around->Before->businessFun->Around後續->After->AfterReturing/AfterThrowing

aspect.jpg

下邊通過spring源碼分析一下,對於切面類和方法的執行順序,spring是如何控制的。

2. spring上下文初始化的時候,第一次創建advisors的緩存時,對切面方法的排序過程

定位到目標類AnnotationAwareAspectJAutoProxyCreator,通過90行的斷點,進一步說明。具體的調用棧情況如下:

findCandidateAdvisors:90, AnnotationAwareAspectJAutoProxyCreator (org.springframework.aop.aspectj.annotation)
shouldSkip:103, AspectJAwareAdvisorAutoProxyCreator (org.springframework.aop.aspectj.autoproxy)
postProcessBeforeInstantiation:248, AbstractAutoProxyCreator (org.springframework.aop.framework.autoproxy)
applyBeanPostProcessorsBeforeInstantiation:1042, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
resolveBeforeInstantiation:1016, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
createBean:471, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
getObject:312, AbstractBeanFactory$1 (org.springframework.beans.factory.support)
getSingleton:230, DefaultSingletonBeanRegistry (org.springframework.beans.factory.support)
doGetBean:308, AbstractBeanFactory (org.springframework.beans.factory.support)
getBean:197, AbstractBeanFactory (org.springframework.beans.factory.support)
preInstantiateSingletons:761, DefaultListableBeanFactory (org.springframework.beans.factory.support)
finishBeanFactoryInitialization:867, AbstractApplicationContext (org.springframework.context.support)
refresh:543, AbstractApplicationContext (org.springframework.context.support)
<init>:139, ClassPathXmlApplicationContext (org.springframework.context.support)
<init>:83, ClassPathXmlApplicationContext (org.springframework.context.support)
main:28, TestOrder (com.stpice.spring.demo.aop.order)
	@Override
	protected List<Advisor> findCandidateAdvisors() {
		// Add all the Spring advisors found according to superclass rules.
		List<Advisor> advisors = super.findCandidateAdvisors();
		// Build Advisors for all AspectJ aspects in the bean factory.
		advisors.addAll(this.aspectJAdvisorsBuilder.buildAspectJAdvisors());//這裏會構建所有的advisors,並添加到list裏面
		return advisors;
	}

進入this.aspectJAdvisorsBuilder.buildAspectJAdvisors()方法。

buildAspectJAdvisors:85, BeanFactoryAspectJAdvisorsBuilder (org.springframework.aop.aspectj.annotation)
findCandidateAdvisors:90, AnnotationAwareAspectJAutoProxyCreator (org.springframework.aop.aspectj.annotation)
...

BeanFactoryAspectJAdvisorsBuilder中的buildAspectJAdvisors方法是真正的構建advisors的方法。這個方法比較長,這裏針對其中比較關鍵的部分代碼進行註釋說明。

	/**
	 * Look for AspectJ-annotated aspect beans in the current bean factory,
	 * and return to a list of Spring AOP Advisors representing them.
	 * <p>Creates a Spring Advisor for each AspectJ advice method.
	 * @return the list of {@link org.springframework.aop.Advisor} beans
	 * @see #isEligibleBean
	 */
	public List<Advisor> buildAspectJAdvisors() {
		List<String> aspectNames = this.aspectBeanNames;//因爲是單例的,初始的時候,切面bean的名字爲null

		if (aspectNames == null) {//第一次爲null的時候,會進入這個分支構建切面bean
			synchronized (this) {//以單例爲鎖進行同步
				aspectNames = this.aspectBeanNames;//重新獲取,防止併發時,其他線程已經進行過初始化
				if (aspectNames == null) {//尚未初始化
					List<Advisor> advisors = new LinkedList<Advisor>();//先構造一個空的鏈表
					aspectNames = new LinkedList<String>();//aspectNames是一個存放切面名字的臨時列表
					String[] beanNames = BeanFactoryUtils.beanNamesForTypeIncludingAncestors(
							this.beanFactory, Object.class, true, false);//從bean工廠中獲取所有的bean名稱
					for (String beanName : beanNames) {
						if (!isEligibleBean(beanName)) {//遍歷判斷是否該bean的類型是否合適自動代理,這裏會調用BeanFactoryAspectJAdvisorsBuilder子類AnnotationAwareAspectJAutoProxyCreator中的isEligibleBean方法,如果不滿足,則繼續遍歷
							continue;
						}
						// We must be careful not to instantiate beans eagerly as in this case they
						// would be cached by the Spring container but would not have been weaved.
						Class<?> beanType = this.beanFactory.getType(beanName);
						if (beanType == null) {
							continue;
						}
						if (this.advisorFactory.isAspect(beanType)) {//滿足則判斷類型是否爲切面
							aspectNames.add(beanName);
							AspectMetadata amd = new AspectMetadata(beanType, beanName);
							if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {//單例的處理方式
								MetadataAwareAspectInstanceFactory factory =
										new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
								List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);//從factory中獲取advisors,這裏涉及到初始獲取各個切面實例中的切面方法時,每個方法的排列順序,後邊會具體進行分析
								if (this.beanFactory.isSingleton(beanName)) {
									this.advisorsCache.put(beanName, classAdvisors);//緩存單例的切面實例
								}
								else {
									this.aspectFactoryCache.put(beanName, factory);//多例對切面工廠進行緩存
								}
								advisors.addAll(classAdvisors);//添加到advisors列表中
							}
							else {
								// Per target or per this.
								if (this.beanFactory.isSingleton(beanName)) {
									throw new IllegalArgumentException("Bean with name '" + beanName +
											"' is a singleton, but aspect instantiation model is not singleton");
								}
								MetadataAwareAspectInstanceFactory factory =
										new PrototypeAspectInstanceFactory(this.beanFactory, beanName);
								this.aspectFactoryCache.put(beanName, factory);
								advisors.addAll(this.advisorFactory.getAdvisors(factory));
							}
						}
					}
					this.aspectBeanNames = aspectNames;//將名字保存到域變量中
					return advisors;//初始化完成直接返回
				}
			}
		}

		if (aspectNames.isEmpty()) {
			return Collections.emptyList();
		}
		List<Advisor> advisors = new LinkedList<Advisor>();
		for (String aspectName : aspectNames) {
			List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName);
			if (cachedAdvisors != null) {
				advisors.addAll(cachedAdvisors);
			}
			else {
				MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName);
				advisors.addAll(this.advisorFactory.getAdvisors(factory));
			}
		}
		return advisors;
	}

ReflectiveAspectJAdvisorFactory類中,會處理所有的advisors中的各個方法,並對方法進行排序包裝。

getAdvisors:135, ReflectiveAspectJAdvisorFactory (org.springframework.aop.aspectj.annotation)
buildAspectJAdvisors:109, BeanFactoryAspectJAdvisorsBuilder (org.springframework.aop.aspectj.annotation)
findCandidateAdvisors:90, AnnotationAwareAspectJAutoProxyCreator (org.springframework.aop.aspectj.annotation)
...

	@Override
	public List<Advisor> getAdvisors(MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
		Class<?> aspectClass = aspectInstanceFactory.getAspectMetadata().getAspectClass();
		String aspectName = aspectInstanceFactory.getAspectMetadata().getAspectName();
		validate(aspectClass);

		// We need to wrap the MetadataAwareAspectInstanceFactory with a decorator
		// so that it will only instantiate once.
		MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
				new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);

		List<Advisor> advisors = new ArrayList<Advisor>();
		for (Method method : getAdvisorMethods(aspectClass)) {//這裏獲取所有advisors方法的時候,會對切面方法進行比較並排序
			Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);//包裝advisor,並且將不是advisor的方法過濾掉
			if (advisor != null) {
				advisors.add(advisor);//加入列表
			}
		}

		// If it's a per target aspect, emit the dummy instantiating aspect.
		if (!advisors.isEmpty() && lazySingletonAspectInstanceFactory.getAspectMetadata().isLazilyInstantiated()) {
			Advisor instantiationAdvisor = new SyntheticInstantiationAdvisor(lazySingletonAspectInstanceFactory);
			advisors.add(0, instantiationAdvisor);
		}

		// Find introduction fields.
		for (Field field : aspectClass.getDeclaredFields()) {
			Advisor advisor = getDeclareParentsAdvisor(field);
			if (advisor != null) {
				advisors.add(advisor);
			}
		}

		return advisors;
	}

getAdvisorMethods:160, ReflectiveAspectJAdvisorFactory (org.springframework.aop.aspectj.annotation)
getAdvisors:135, ReflectiveAspectJAdvisorFactory (org.springframework.aop.aspectj.annotation)
buildAspectJAdvisors:109, BeanFactoryAspectJAdvisorsBuilder (org.springframework.aop.aspectj.annotation)
findCandidateAdvisors:90, AnnotationAwareAspectJAutoProxyCreator (org.springframework.aop.aspectj.annotation)
...

	private List<Method> getAdvisorMethods(Class<?> aspectClass) {
		final List<Method> methods = new ArrayList<Method>();
		ReflectionUtils.doWithMethods(aspectClass, new ReflectionUtils.MethodCallback() {
			@Override
			public void doWith(Method method) throws IllegalArgumentException {
				// Exclude pointcuts 這裏跳過了切點註解的方法
				if (AnnotationUtils.getAnnotation(method, Pointcut.class) == null) {
					methods.add(method);
				}
			}
		});
		Collections.sort(methods, METHOD_COMPARATOR);//對所有的advisors方法進行排序,使用的METHOD_COMPARATOR,放在類靜態代碼塊中,下邊會說明
		return methods;
	}

上述代碼中的methods,包含了該切面對象的所有方法, 包括父類的方法等,如下:

0 = {Method@1880} "public void com.stpice.spring.demo.aop.order.AspectJOrderHigh.beforeTest()"
1 = {Method@1881} "public void com.stpice.spring.demo.aop.order.AspectJOrderHigh.afterTest()"
2 = {Method@1882} "public java.lang.Object com.stpice.spring.demo.aop.order.AspectJOrderHigh.aroundTest(org.aspectj.lang.ProceedingJoinPoint) throws java.lang.Throwable"
3 = {Method@1883} "public int com.stpice.spring.demo.aop.order.AspectJOrderHigh.getOrder()"
4 = {Method@1884} "protected void java.lang.Object.finalize() throws java.lang.Throwable"
5 = {Method@1885} "public final void java.lang.Object.wait() throws java.lang.InterruptedException"
6 = {Method@1886} "public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException"
7 = {Method@1887} "public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException"
8 = {Method@1888} "public boolean java.lang.Object.equals(java.lang.Object)"
9 = {Method@1889} "public java.lang.String java.lang.Object.toString()"
10 = {Method@1890} "public native int java.lang.Object.hashCode()"
11 = {Method@1891} "public final native java.lang.Class java.lang.Object.getClass()"
12 = {Method@1892} "protected native java.lang.Object java.lang.Object.clone() throws java.lang.CloneNotSupportedException"
13 = {Method@1893} "public final native void java.lang.Object.notify()"
14 = {Method@1894} "public final native void java.lang.Object.notifyAll()"
15 = {Method@1895} "private static native void java.lang.Object.registerNatives()"

在類ReflectiveAspectJAdvisorFactory初始化的時候,會實例化METHOD_COMPARATOR,保存好。

	private static final Comparator<Method> METHOD_COMPARATOR;

	static {
        //註冊兩個比較器,先根據下邊聲明的註解類順序,進行比對,如果註解相同的話,再把目標方法轉換爲String,調用String的compareTo()方法進行比較
		CompoundComparator<Method> comparator = new CompoundComparator<Method>();
		comparator.addComparator(new ConvertingComparator<Method, Annotation>(//將方法轉換爲註解,然後進行註解對比
				new InstanceComparator<Annotation>(
						Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class),//實例比較器,按照上邊切面類的順序,對切面方法註解進行判斷比較
				new Converter<Method, Annotation>() {
					@Override
					public Annotation convert(Method method) {
						AspectJAnnotation<?> annotation =
						AbstractAspectJAdvisorFactory.findAspectJAnnotationOnMethod(method);
						return (annotation != null ? annotation.getAnnotation() : null);
					}//轉換器會將比較的目標對象轉換爲切面方法的註解返回
				}));
		comparator.addComparator(new ConvertingComparator<Method, String>(//將方法轉換爲String,然後進行對比
				new Converter<Method, String>() {
					@Override
					public String convert(Method method) {
						return method.getName();//轉換器會將目標對象的轉換爲String再進行比對
					}
				}));
		METHOD_COMPARATOR = comparator;
	}

compare方法中會遍歷兩個Comparator,然後分別進行比較。

compare:173, CompoundComparator (org.springframework.util.comparator)
countRunAndMakeAscending:355, TimSort (java.util)
sort:220, TimSort (java.util)
sort:1512, Arrays (java.util)
sort:1460, ArrayList (java.util)
sort:175, Collections (java.util)
getAdvisorMethods:170, ReflectiveAspectJAdvisorFactory (org.springframework.aop.aspectj.annotation)
getAdvisors:135, ReflectiveAspectJAdvisorFactory (org.springframework.aop.aspectj.annotation)
buildAspectJAdvisors:109, BeanFactoryAspectJAdvisorsBuilder (org.springframework.aop.aspectj.annotation)
findCandidateAdvisors:90, AnnotationAwareAspectJAutoProxyCreator (org.springframework.aop.aspectj.annotation)
...

	public int compare(T o1, T o2) {
		Assert.state(this.comparators.size() > 0,
				"No sort definitions have been added to this CompoundComparator to compare");
		for (InvertibleComparator comparator : this.comparators) {
			int result = comparator.compare(o1, o2);
			if (result != 0) {
				return result;
			}
		}
		return 0;
	}

compare:56, InstanceComparator (org.springframework.util.comparator)
compare:81, ConvertingComparator (org.springframework.core.convert.converter)
compare:89, InvertibleComparator (org.springframework.util.comparator)
compare:174, CompoundComparator (org.springframework.util.comparator)
countRunAndMakeAscending:355, TimSort (java.util)
sort:220, TimSort (java.util)
sort:1512, Arrays (java.util)
sort:1460, ArrayList (java.util)
sort:175, Collections (java.util)
getAdvisorMethods:170, ReflectiveAspectJAdvisorFactory (org.springframework.aop.aspectj.annotation)
getAdvisors:135, ReflectiveAspectJAdvisorFactory (org.springframework.aop.aspectj.annotation)
buildAspectJAdvisors:109, BeanFactoryAspectJAdvisorsBuilder (org.springframework.aop.aspectj.annotation)
findCandidateAdvisors:90, AnnotationAwareAspectJAutoProxyCreator (org.springframework.aop.aspectj.annotation)
...

	@Override
	public int compare(T o1, T o2) {
		int i1 = getOrder(o1);//通過調用getOrder獲取順序
		int i2 = getOrder(o2);
		return (i1 < i2 ? -1 : (i1 == i2 ? 0 : 1));//<,=,>分別返回-1,0,1
	}

	private int getOrder(T object) {
		if (object != null) {
			for (int i = 0; i < this.instanceOrder.length; i++) {
				if (this.instanceOrder[i].isInstance(object)) {//看命中列表中的第幾個,表示順序是多少,通過順序號進行對比
					return i;
				}
			}
		}
		return this.instanceOrder.length;
	}

0 = {Class@1755} "interface org.aspectj.lang.annotation.Around"
1 = {Class@1751} "interface org.aspectj.lang.annotation.Before"
2 = {Class@1753} "interface org.aspectj.lang.annotation.After"
3 = {Class@2064} "interface org.aspectj.lang.annotation.AfterReturning"
4 = {Class@2065} "interface org.aspectj.lang.annotation.AfterThrowing"

上邊即時上文中提供的切面方法的順序,根據這個順序進行對比。

另外,如果兩個方法上的註解相同,那麼會觸發第二個比較器,String的比較器,如下:

    /**
     * Compares two strings lexicographically.
     * The comparison is based on the Unicode value of each character in
     * the strings. The character sequence represented by this
     * {@code String} object is compared lexicographically to the
     * character sequence represented by the argument string. The result is
     * a negative integer if this {@code String} object
     * lexicographically precedes the argument string. The result is a
     * positive integer if this {@code String} object lexicographically
     * follows the argument string. The result is zero if the strings
     * are equal; {@code compareTo} returns {@code 0} exactly when
     * the {@link #equals(Object)} method would return {@code true}.
     * <p>
     * This is the definition of lexicographic ordering. If two strings are
     * different, then either they have different characters at some index
     * that is a valid index for both strings, or their lengths are different,
     * or both. If they have different characters at one or more index
     * positions, let <i>k</i> be the smallest such index; then the string
     * whose character at position <i>k</i> has the smaller value, as
     * determined by using the &lt; operator, lexicographically precedes the
     * other string. In this case, {@code compareTo} returns the
     * difference of the two character values at position {@code k} in
     * the two string -- that is, the value:
     * <blockquote><pre>
     * this.charAt(k)-anotherString.charAt(k)
     * </pre></blockquote>
     * If there is no index position at which they differ, then the shorter
     * string lexicographically precedes the longer string. In this case,
     * {@code compareTo} returns the difference of the lengths of the
     * strings -- that is, the value:
     * <blockquote><pre>
     * this.length()-anotherString.length()
     * </pre></blockquote>
     *
     * @param   anotherString   the {@code String} to be compared.
     * @return  the value {@code 0} if the argument string is equal to
     *          this string; a value less than {@code 0} if this string
     *          is lexicographically less than the string argument; and a
     *          value greater than {@code 0} if this string is
     *          lexicographically greater than the string argument.
     */
    public int compareTo(String anotherString) {
        int len1 = value.length;
        int len2 = anotherString.value.length;
        int lim = Math.min(len1, len2);
        char v1[] = value;
        char v2[] = anotherString.value;

        int k = 0;
        while (k < lim) {
            char c1 = v1[k];
            char c2 = v2[k];
            if (c1 != c2) {
                return c1 - c2;
            }
            k++;
        }
        return len1 - len2;
    }

註釋已經解釋的很詳細了,這裏大致描述一下,兩個字符串比較,只比較二者較短的字母長度,如果遇到當前實例的字符串大,返回正數,如果小,返回負數,如果等,繼續向下比較,如果可比較的長度內完全相同,那麼長度較短的小。大致是這麼個比較過程,總結一下,大致就是字母序比較,如果前N個字符相同,

getAdvisor:205, ReflectiveAspectJAdvisorFactory (org.springframework.aop.aspectj.annotation)
getAdvisors:136, ReflectiveAspectJAdvisorFactory (org.springframework.aop.aspectj.annotation)
buildAspectJAdvisors:109, BeanFactoryAspectJAdvisorsBuilder (org.springframework.aop.aspectj.annotation)
findCandidateAdvisors:90, AnnotationAwareAspectJAutoProxyCreator (org.springframework.aop.aspectj.annotation)
...

	@Override
	public Advisor getAdvisor(Method candidateAdviceMethod, MetadataAwareAspectInstanceFactory aspectInstanceFactory,
			int declarationOrderInAspect, String aspectName) {

		validate(aspectInstanceFactory.getAspectMetadata().getAspectClass());

		AspectJExpressionPointcut expressionPointcut = getPointcut(
				candidateAdviceMethod, aspectInstanceFactory.getAspectMetadata().getAspectClass());//獲取方法對應的切面,如果爲null,則不是切面方法,跳過該條
		if (expressionPointcut == null) {
			return null;
		}

		return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
				this, aspectInstanceFactory, declarationOrderInAspect, aspectName);//包裝切面方法
	}

通過上文描述,advisors的初始化工作已經完成了。總結一下,對應不同的advisors實例,只是添加到了列表中,並且在BeanFactoryAspectJAdvisorsBuilder的域變量中做了緩存,尚未排序,只是對同一個類型的實例中不同的切面方法進行了排序,排序使用了兩個比較器,首先是掃描方法註解,根據Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class的順序進行排序,如果註解相同,根據切面方法的方法名(包含包名和類名的完整名稱),使用StringcompareTo()方法進行對比,簡單說是根據字母序和字母長度進行排序,完成後,所有的advisor方法會按照其屬於不同的切面類,以beanName作爲key,保存到緩存中,以備後續觸發切面邏輯時進行使用。

2. 在每次觸發切面方法的時候,進行匹配的方法篩選,並對切面類進行排序

在調用切面目標方法的時候,會進入AbstractAdvisorAutoProxyCreator方法中的findEligibleAdvisors函數,並且隨後會再次進入BeanFactoryAspectJAdvisorsBuilder中的buildAspectJAdvisors,具體如下兩部分代碼。

findEligibleAdvisors:88, AbstractAdvisorAutoProxyCreator (org.springframework.aop.framework.autoproxy)
getAdvicesAndAdvisorsForBean:70, AbstractAdvisorAutoProxyCreator (org.springframework.aop.framework.autoproxy)
wrapIfNecessary:346, AbstractAutoProxyCreator (org.springframework.aop.framework.autoproxy)
postProcessAfterInitialization:298, AbstractAutoProxyCreator (org.springframework.aop.framework.autoproxy)
applyBeanPostProcessorsAfterInitialization:421, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
initializeBean:1635, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
doCreateBean:553, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
createBean:481, AbstractAutowireCapableBeanFactory (org.springframework.beans.factory.support)
getObject:312, AbstractBeanFactory$1 (org.springframework.beans.factory.support)
getSingleton:230, DefaultSingletonBeanRegistry (org.springframework.beans.factory.support)
doGetBean:308, AbstractBeanFactory (org.springframework.beans.factory.support)
getBean:197, AbstractBeanFactory (org.springframework.beans.factory.support)
preInstantiateSingletons:761, DefaultListableBeanFactory (org.springframework.beans.factory.support)
finishBeanFactoryInitialization:867, AbstractApplicationContext (org.springframework.context.support)
refresh:543, AbstractApplicationContext (org.springframework.context.support)
<init>:139, ClassPathXmlApplicationContext (org.springframework.context.support)
<init>:83, ClassPathXmlApplicationContext (org.springframework.context.support)
main:28, TestOrder (com.stpice.spring.demo.aop.order)

/**
 * Find all eligible Advisors for auto-proxying this class.
 * @param beanClass the clazz to find advisors for
 * @param beanName the name of the currently proxied bean
 * @return the empty List, not {@code null},
 * if there are no pointcuts or interceptors
 * @see #findCandidateAdvisors
 * @see #sortAdvisors
 * @see #extendAdvisors
 */
protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
	List<Advisor> candidateAdvisors = findCandidateAdvisors();//查到到候補的advisors,這個查出來的是所有的advisors,後邊會具體說明
	List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);//找到合適的advisors,這是針對candidateAdvisors,根據特定的bean類型和名稱過濾
	extendAdvisors(eligibleAdvisors);
	if (!eligibleAdvisors.isEmpty()) {
		eligibleAdvisors = sortAdvisors(eligibleAdvisors);//對篩選出的advisors進行排序
	}
	return eligibleAdvisors;
}

buildAspectJAdvisors:85, BeanFactoryAspectJAdvisorsBuilder (org.springframework.aop.aspectj.annotation)
findCandidateAdvisors:90, AnnotationAwareAspectJAutoProxyCreator (org.springframework.aop.aspectj.annotation)
findEligibleAdvisors:88, AbstractAdvisorAutoProxyCreator (org.springframework.aop.framework.autoproxy)
...

	/**
	 * Look for AspectJ-annotated aspect beans in the current bean factory,
	 * and return to a list of Spring AOP Advisors representing them.
	 * <p>Creates a Spring Advisor for each AspectJ advice method.
	 * @return the list of {@link org.springframework.aop.Advisor} beans
	 * @see #isEligibleBean
	 */
	public List<Advisor> buildAspectJAdvisors() {
		List<String> aspectNames = this.aspectBeanNames;

		if (aspectNames == null) {//再次進入這個方法的時候,由於該實例中的aspectBeanNames已經在初始化的時候進行賦值,所以aspectNames不爲null,不會進入這個分支。簡單來說,就是這裏只有在初始化時候進入一次
			synchronized (this) {
				aspectNames = this.aspectBeanNames;

	/**
	 * Look for AspectJ-annotated aspect beans in the current bean factory,
	 * and return to a list of Spring AOP Advisors representing them.
	 * <p>Creates a Spring Advisor for each AspectJ advice method.
	 * @return the list of {@link org.springframework.aop.Advisor} beans
	 * @see #isEligibleBean
	 */
	public List<Advisor> buildAspectJAdvisors() {
		List<String> aspectNames = this.aspectBeanNames;

		if (aspectNames == null) {...}

		if (aspectNames.isEmpty()) {//如果沒有緩存切面類的名稱,則沒有切面,返回空集合
			return Collections.emptyList();
		}
		List<Advisor> advisors = new LinkedList<Advisor>();
		for (String aspectName : aspectNames) {
			List<Advisor> cachedAdvisors = this.advisorsCache.get(aspectName);//如果有切面類,則從緩存中,按照對應的切面名稱取出實際的advisors,然後添加到上邊實例化的Advisor鏈表中
			if (cachedAdvisors != null) {
				advisors.addAll(cachedAdvisors);
			}
			else {
				MetadataAwareAspectInstanceFactory factory = this.aspectFactoryCache.get(aspectName);//這裏對應非單例模式的切面,從切面工廠緩存中獲取到切面工廠類
				advisors.addAll(this.advisorFactory.getAdvisors(factory));//通過調用getAdvisors方法,產生advisors,加入列表
			}
		}
		return advisors;
	}

上邊代碼中對應的advisor,都是一個對應到具體的切面方法的。

獲取到advisors的列表後,返回之前調用的findEligibleAdivsors方法,繼續調用sortAdvisors對各個切面方法進行排序,這裏的排序不會打亂每個匹配的切面類中各個切面方法的順序,只會根據切面類的Order對各個類進行排序,由於現在的列表中都是對應切面方法,而Advisor這個對象中包含了它所在的切面類是哪個。下邊會對應進入sortAdvisors方法看對切面類排序的過程。

findEligibleAdvisors:92, AbstractAdvisorAutoProxyCreator (org.springframework.aop.framework.autoproxy)
...

	/**
	 * Find all eligible Advisors for auto-proxying this class.
	 * @param beanClass the clazz to find advisors for
	 * @param beanName the name of the currently proxied bean
	 * @return the empty List, not {@code null},
	 * if there are no pointcuts or interceptors
	 * @see #findCandidateAdvisors
	 * @see #sortAdvisors
	 * @see #extendAdvisors
	 */
	protected List<Advisor> findEligibleAdvisors(Class<?> beanClass, String beanName) {
		List<Advisor> candidateAdvisors = findCandidateAdvisors();
		List<Advisor> eligibleAdvisors = findAdvisorsThatCanApply(candidateAdvisors, beanClass, beanName);
		extendAdvisors(eligibleAdvisors);
		if (!eligibleAdvisors.isEmpty()) {
			eligibleAdvisors = sortAdvisors(eligibleAdvisors);//對切面類通過order進行排序,不會改變每個切面類中對應的切面方法的順序
		}
		return eligibleAdvisors;
	}

sortAdvisors:70, AspectJAwareAdvisorAutoProxyCreator (org.springframework.aop.aspectj.autoproxy)
findEligibleAdvisors:92, AbstractAdvisorAutoProxyCreator (org.springframework.aop.framework.autoproxy)
...

	protected List<Advisor> sortAdvisors(List<Advisor> advisors) {
		List<PartiallyComparableAdvisorHolder> partiallyComparableAdvisors =
				new ArrayList<PartiallyComparableAdvisorHolder>(advisors.size());//先根據切面列表中切面的個數,創建一個用於比較切面的Holder類列表,這裏名字爲“部分比較”,個人猜測是隻做了類order的比較
		for (Advisor element : advisors) {
			partiallyComparableAdvisors.add(
					new PartiallyComparableAdvisorHolder(element, DEFAULT_PRECEDENCE_COMPARATOR));//將原始的advisor類進行包裝,放入列表中,這裏用到的比較器是DEFAULT_PRECEDENCE_COMPARATOR,默認的一個比較器,下邊會對這個比較器進行具體分析
		}
		List<PartiallyComparableAdvisorHolder> sorted =
				PartialOrder.sort(partiallyComparableAdvisors);//實際的排序函數,這個PartialOrder方法是aspectj包提供的一個排序方法,簡單來說,內部使用了簡單排序中的選擇排序,後邊會具體後說明
		if (sorted != null) {//排序後,再從包裝類中將advisor取出來,重新放回列表中返回
			List<Advisor> result = new ArrayList<Advisor>(advisors.size());
			for (PartiallyComparableAdvisorHolder pcAdvisor : sorted) {
				result.add(pcAdvisor.getAdvisor());
			}
			return result;
		}
		else {
			return super.sortAdvisors(advisors);//如果PartialOrder比較方法返回結果爲null,則使用父類AbstractAdvisorAutoProxyCreator的排序方法,AnnotationAwareOrderComparator.sort(advisors);146
		}
	}

AspectJAwareAdvisorAutoProxyCreator.png

AspectJPrecedenceComparator的構造函數中,創建了一個AnnotationAwareOrderComparator比較器的實例,其中關鍵處在於獲取order的方法,即findOrder,如下AnnotationAwareOrderComparator類中代碼:

	/**
	 * This implementation checks for {@link Order @Order} or
	 * {@link javax.annotation.Priority @Priority} on various kinds of
	 * elements, in addition to the {@link org.springframework.core.Ordered}
	 * check in the superclass.
	 */
	@Override
	protected Integer findOrder(Object obj) {
		// Check for regular Ordered interface
		Integer order = super.findOrder(obj);//調用父類方法,獲取實現了Ordered接口的實例的order值,這裏比較時使用的獲取order就是調用這個方法,後文會繼續說明
		if (order != null) {
			return order;
		}

		// Check for @Order and @Priority on various kinds of elements
		if (obj instanceof Class) {//如果是class,通過OrderUtils獲取order屬性值
			return OrderUtils.getOrder((Class<?>) obj);//這裏面會獲取類上@Order的註解的值
		}
		else if (obj instanceof Method) {
			Order ann = AnnotationUtils.findAnnotation((Method) obj, Order.class);//如果目標是方法,從方法上獲取@Order註解
			if (ann != null) {
				return ann.value();
			}
		}
		else if (obj instanceof AnnotatedElement) {
			Order ann = AnnotationUtils.getAnnotation((AnnotatedElement) obj, Order.class);
			if (ann != null) {
				return ann.value();
			}
		}
		else if (obj != null) {
			order = OrderUtils.getOrder(obj.getClass());
			if (order == null && obj instanceof DecoratingProxy) {
				order = OrderUtils.getOrder(((DecoratingProxy) obj).getDecoratedClass());
			}
		}

		return order;
	}

上邊這個比較,在上文中的父類比較器,也是同一個,都會觸發這個邏輯,獲取order屬性,然後對order屬性進行比較後排序。

	/**
	 * Sort the given List with a default AnnotationAwareOrderComparator.
	 * <p>Optimized to skip sorting for lists with size 0 or 1,
	 * in order to avoid unnecessary array extraction.
	 * @param list the List to sort
	 * @see java.util.Collections#sort(java.util.List, java.util.Comparator)
	 */
	public static void sort(List<?> list) {
		if (list.size() > 1) {
			Collections.sort(list, INSTANCE);//排序使用的Collections的sort方法,實例即爲上文提到的AnnotationAwareOrderComparator實例
		}
	}

3. 下邊說明具體的排序方法

List<PartiallyComparableAdvisorHolder> sorted = PartialOrder.sort(partiallyComparableAdvisors);主要是這一行代碼,進入代碼發現時aspectjweaver包中的實現的一個排序方法。下邊這段代碼,是在實際觸發切面目標的業務方法時候,每次都會執行的,會對篩選出來符合目標業務方法的切面,做一次排序,所有的實現都在這個PartialOrder.sort()方法中。具體如下:

sort:119, PartialOrder (org.aspectj.util)
sortAdvisors:77, AspectJAwareAdvisorAutoProxyCreator (org.springframework.aop.aspectj.autoproxy)
findEligibleAdvisors:92, AbstractAdvisorAutoProxyCreator (org.springframework.aop.framework.autoproxy)
getAdvicesAndAdvisorsForBean:70, AbstractAdvisorAutoProxyCreator (org.springframework.aop.framework.autoproxy)
...

	/**
	 * @param objects must all implement PartialComparable
	 * 
	 * @returns the same members as objects, but sorted according to their partial order. returns null if the objects are cyclical
	 * 
	 */
	public static List sort(List objects) {
		// lists of size 0 or 1 don't need any sorting
		if (objects.size() < 2) {//一個的話,不用排序,直接返回
			return objects;
		}

		// ??? we might want to optimize a few other cases of small size

		// ??? I don't like creating this data structure, but it does give good
		// ??? separation of concerns.
        // 這裏上邊解釋了半天,是他不想構造這個數據結構,但是又覺得這個數據結構可以分離很多複雜的邏輯
        // 下邊這個方法是構造了一個SortObject,將advisors列表中每個元素,都用SortObject包裝一下,包裝後,裏面會保存比當前這個advisor大的元素有幾個,小的有幾個,這樣兩個列表,後邊的邏輯中會根據這兩個列表中的值,進行具體的排序比較
		List<SortObject> sortList = new LinkedList<SortObject>(); // objects.size());
		for (Iterator i = objects.iterator(); i.hasNext();) {
			addNewPartialComparable(sortList, (PartialComparable) i.next());//將advisor包裝成SortObject,並加入sortList
		}

		// System.out.println(sortList);

		// now we have built our directed graph
		// use a simple sort algorithm from here
		// can increase efficiency later
		// List ret = new ArrayList(objects.size());
		final int N = objects.size();
		for (int index = 0; index < N; index++) {//下邊會進行兩次嵌套的遍歷,從sortList中選出最小的,放入objects中
			// System.out.println(sortList);
			// System.out.println("-->" + ret);

			SortObject leastWithNoSmallers = null;

			for (Iterator i = sortList.iterator(); i.hasNext();) {
				SortObject so = (SortObject) i.next();
				// System.out.println(so);
				if (so.hasNoSmallerObjects()) {//判斷有無更小的對象,如果沒有,則當前的對象爲最小
					if (leastWithNoSmallers == null || so.object.fallbackCompareTo(leastWithNoSmallers.object) < 0) {//fallbackCompareTo總會返回0
						leastWithNoSmallers = so;
					}
				}
			}

			if (leastWithNoSmallers == null) {
				return null;
			}

			removeFromGraph(sortList, leastWithNoSmallers);//從sortList中移除最小的對象,這個會遍歷sortList中的所有對象,從各個對象保存比自己小的對象的列表中移除掉,後邊會具體說
			objects.set(index, leastWithNoSmallers.object);//從SortObject中取出advisor,放入objects列表中
		}

		return objects;
	}

	private static void addNewPartialComparable(List<SortObject> graph, PartialComparable o) {
		SortObject so = new SortObject(o);
		for (Iterator<SortObject> i = graph.iterator(); i.hasNext();) {
			SortObject other = i.next();
			so.addDirectedLinks(other);//遍歷現有的graph列表,將新元素與老元素進行對比並添加關聯關係,後文具體說明
		}
		graph.add(so);
	}

AspectJAwareAdvisorAutoProxyCreator中的fallbackCompareTo總會返回0,所以上邊邏輯中只要leastWithNoSmallersnull,那麼纔會觸發賦值。

		@Override
		public int fallbackCompareTo(Object obj) {
			return 0;
		}

PartialOrder中的這個方法,會遍歷刪除所有對象,從smallerObjects中刪除o

	private static void removeFromGraph(List<SortObject> graph, SortObject o) {
		for (Iterator<SortObject> i = graph.iterator(); i.hasNext();) {
			SortObject other = i.next();

			if (o == other) {
				i.remove();//刪除graph中的對象o
			}
			// ??? could use this to build up a new queue of objects with no
			// ??? smaller ones
			other.removeSmallerObject(o);//刪除graph其他對象中的smallerObjects中的o
		}
	}

PartialOrder中的SortObject對象如下:

	private static class SortObject {
		PartialComparable object;
		List<SortObject> smallerObjects = new LinkedList<SortObject>();//保存比自己小的對象列表
		List<SortObject> biggerObjects = new LinkedList<SortObject>();//保存比自己大的對象列表

		public SortObject(PartialComparable o) {
			object = o;
		}

		boolean hasNoSmallerObjects() {
			return smallerObjects.size() == 0;
		}

		boolean removeSmallerObject(SortObject o) {
			smallerObjects.remove(o);
			return hasNoSmallerObjects();
		}

		void addDirectedLinks(SortObject other) {//這裏是上文提到的添加大小關聯關係的方法
			int cmp = object.compareTo(other.object);//先做比較,這裏的object裏面的比較器是AspectJPrecedenceComparator,上文提到過
			if (cmp == 0) {
				return;
			}
			if (cmp > 0) {//根據大小,會在兩個對象中的smallerObjects、biggerObjects中分別加入對應的關聯關係
				this.smallerObjects.add(other);
				other.biggerObjects.add(this);
			} else {
				this.biggerObjects.add(other);
				other.smallerObjects.add(this);
			}
		}

		public String toString() {
			return object.toString(); // +smallerObjects+biggerObjects;
		}
	}

int cmp = object.compareTo(other.object);中的方法,具體如下:

	@Override
	public int compare(Advisor o1, Advisor o2) {
		int advisorPrecedence = this.advisorComparator.compare(o1, o2);//比較o1,o2,這裏的advisorComparator是AnnotationAwareOrderComparator的一個實例
		if (advisorPrecedence == SAME_PRECEDENCE && declaredInSameAspect(o1, o2)) {
			advisorPrecedence = comparePrecedenceWithinAspect(o1, o2);
		}
		return advisorPrecedence;
	}

AnnotationAwareOrderComparator.png

這個是AnnotationAwareOrderComparator的關聯關係,實際上的調用的OrderComparatordoCompare方法,如下:

doCompare:77, OrderComparator (org.springframework.core)
compare:73, OrderComparator (org.springframework.core)
compare:81, AspectJPrecedenceComparator (org.springframework.aop.aspectj.autoproxy)
compare:49, AspectJPrecedenceComparator (org.springframework.aop.aspectj.autoproxy)
compareTo:132, AspectJAwareAdvisorAutoProxyCreator$PartiallyComparableAdvisorHolder (org.springframework.aop.aspectj.autoproxy)
addDirectedLinks:71, PartialOrder$SortObject (org.aspectj.util)
addNewPartialComparable:93, PartialOrder (org.aspectj.util)
sort:129, PartialOrder (org.aspectj.util)
sortAdvisors:77, AspectJAwareAdvisorAutoProxyCreator (org.springframework.aop.aspectj.autoproxy)
findEligibleAdvisors:92, AbstractAdvisorAutoProxyCreator (org.springframework.aop.framework.autoproxy)
getAdvicesAndAdvisorsForBean:70, AbstractAdvisorAutoProxyCreator (org.springframework.aop.framework.autoproxy)
...

	private int doCompare(Object o1, Object o2, OrderSourceProvider sourceProvider) {
		boolean p1 = (o1 instanceof PriorityOrdered);//會優先判斷是否是PriorityOrdered接口的實現
		boolean p2 = (o2 instanceof PriorityOrdered);
		if (p1 && !p2) {
			return -1;
		}
		else if (p2 && !p1) {
			return 1;
		}

		// Direct evaluation instead of Integer.compareTo to avoid unnecessary object creation.
		int i1 = getOrder(o1, sourceProvider);//調用獲取order屬性值
		int i2 = getOrder(o2, sourceProvider);
		return (i1 < i2) ? -1 : (i1 > i2) ? 1 : 0;
	}

getOrder:100, OrderComparator (org.springframework.core)
doCompare:87, OrderComparator (org.springframework.core)
compare:73, OrderComparator (org.springframework.core)
compare:81, AspectJPrecedenceComparator (org.springframework.aop.aspectj.autoproxy)
compare:49, AspectJPrecedenceComparator (org.springframework.aop.aspectj.autoproxy)
compareTo:132, AspectJAwareAdvisorAutoProxyCreator$PartiallyComparableAdvisorHolder (org.springframework.aop.aspectj.autoproxy)
addDirectedLinks:71, PartialOrder$SortObject (org.aspectj.util)
addNewPartialComparable:93, PartialOrder (org.aspectj.util)
sort:129, PartialOrder (org.aspectj.util)
sortAdvisors:77, AspectJAwareAdvisorAutoProxyCreator (org.springframework.aop.aspectj.autoproxy)
findEligibleAdvisors:92, AbstractAdvisorAutoProxyCreator (org.springframework.aop.framework.autoproxy)
getAdvicesAndAdvisorsForBean:70, AbstractAdvisorAutoProxyCreator (org.springframework.aop.framework.autoproxy)
...

	/**
	 * Determine the order value for the given object.
	 * <p>The default implementation checks against the given {@link OrderSourceProvider}
	 * using {@link #findOrder} and falls back to a regular {@link #getOrder(Object)} call.
	 * @param obj the object to check
	 * @return the order value, or {@code Ordered.LOWEST_PRECEDENCE} as fallback
	 */
	private int getOrder(Object obj, OrderSourceProvider sourceProvider) {
		Integer order = null;
		if (sourceProvider != null) {
			Object orderSource = sourceProvider.getOrderSource(obj);
			if (orderSource != null && orderSource.getClass().isArray()) {
				Object[] sources = ObjectUtils.toObjectArray(orderSource);
				for (Object source : sources) {
					order = findOrder(source);
					if (order != null) {
						break;
					}
				}
			}
			else {
				order = findOrder(orderSource);
			}
		}
		return (order != null ? order : getOrder(obj));//沒有配置provider,直接調用getOrder中的findeOrder方法,這個方法是在子類AnnotationAwareOrderComparator中實現的,在上文中已經分析過
	}

getOrder:127, BeanFactoryAspectInstanceFactory (org.springframework.aop.aspectj.annotation)
getOrder:87, LazySingletonAspectInstanceFactoryDecorator (org.springframework.aop.aspectj.annotation)
getOrder:173, InstantiationModelAwarePointcutAdvisorImpl (org.springframework.aop.aspectj.annotation)
findOrder:139, OrderComparator (org.springframework.core)
findOrder:64, AnnotationAwareOrderComparator (org.springframework.core.annotation)
getOrder:127, OrderComparator (org.springframework.core)
getOrder:116, OrderComparator (org.springframework.core)
doCompare:87, OrderComparator (org.springframework.core)
compare:73, OrderComparator (org.springframework.core)
compare:81, AspectJPrecedenceComparator (org.springframework.aop.aspectj.autoproxy)
compare:49, AspectJPrecedenceComparator (org.springframework.aop.aspectj.autoproxy)
compareTo:132, AspectJAwareAdvisorAutoProxyCreator$PartiallyComparableAdvisorHolder (org.springframework.aop.aspectj.autoproxy)
addDirectedLinks:71, PartialOrder$SortObject (org.aspectj.util)
addNewPartialComparable:93, PartialOrder (org.aspectj.util)
sort:129, PartialOrder (org.aspectj.util)
sortAdvisors:77, AspectJAwareAdvisorAutoProxyCreator (org.springframework.aop.aspectj.autoproxy)
findEligibleAdvisors:92, AbstractAdvisorAutoProxyCreator (org.springframework.aop.framework.autoproxy)
getAdvicesAndAdvisorsForBean:70, AbstractAdvisorAutoProxyCreator (org.springframework.aop.framework.autoproxy)
...

	/**
	 * Determine the order for this factory's target aspect, either
	 * an instance-specific order expressed through implementing the
	 * {@link org.springframework.core.Ordered} interface (only
	 * checked for singleton beans), or an order expressed through the
	 * {@link org.springframework.core.annotation.Order} annotation
	 * at the class level.
	 * @see org.springframework.core.Ordered
	 * @see org.springframework.core.annotation.Order
	 */
	@Override
	public int getOrder() {//這裏會追溯到BeanFactoryAspectInstanaceFactory類中的方法
		Class<?> type = this.beanFactory.getType(this.name);
		if (type != null) {
			if (Ordered.class.isAssignableFrom(type) && this.beanFactory.isSingleton(this.name)) {//判斷類型是否匹配,是否是單例
				return ((Ordered) this.beanFactory.getBean(this.name)).getOrder();//會從beanFactory中獲取到這個bean,然後調用bean裏面的getOrder方法,獲取order值
			}
			return OrderUtils.getOrder(type, Ordered.LOWEST_PRECEDENCE);//條件不匹配,即沒有實現Ordered接口,或者不是單例,那麼返回最低優先級,即Integer的最大值2147483647
		}
		return Ordered.LOWEST_PRECEDENCE;
	}

BeanFactoryAspectInstanaceFactory.png

通過上邊的分析,就可以瞭解最終是如何調用到切面類的getOrder方法,並根據order的值進行排序的。

4. 入口方法簡介

從main方法的代碼跟蹤進入,發現advisors的生成context初始化的時候只會做一次,然後就將所有的advisors保存在實例的域變量中的一個緩存中,後續都會從這個緩存中讀取。

初始化會調用AbstractApplicationContext中的refresh方法,進一步調用finishBeanFactoryInitialization方法進行單例的實例化。

refresh:543, AbstractApplicationContext (org.springframework.context.support)
<init>:139, ClassPathXmlApplicationContext (org.springframework.context.support)
<init>:83, ClassPathXmlApplicationContext (org.springframework.context.support)
main:28, TestOrder (com.stpice.spring.demo.aop.order)

				// Check for listener beans and register them.
				registerListeners();

				// Instantiate all remaining (non-lazy-init) singletons.
				finishBeanFactoryInitialization(beanFactory);//進行單例實例化,因爲我配置的切面爲單例

				// Last step: publish corresponding event.
				finishRefresh();

5. 總結

通過上文的分析,總結切面的順序控制如下:

  • 初始化時,將所有切面加載到一個域成員變量的Map緩存中,加載時會將每個切面類中的切面方法進行排序
  • 切面方法中的排序方式,首先根據切面註解觸發的順序排序,然後根據字母序進行排序
  • 初始化完成後,每個切面類中的切面方法的順序就不會再次改變了
  • 每次調用切面命中的業務代碼時,會觸發切面掃描,篩選出匹配的切面方法,根據切面方法所在的切面類,通過order屬性的值,做一次排序,這次排序不會更改之前同一個類型中切面方法的相對順序
  • 根據上邊幾步的排序結果,依次觸發切面的邏輯
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章