使用spring版本爲4.3.22
1. 簡介
對於同一個目標方法而言,切面觸發的順序如下:
Around->Before->businessFun->Around後續->After->AfterReturing/AfterThrowing
。
下邊通過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 < 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
的順序進行排序,如果註解相同,根據切面方法的方法名(包含包名和類名的完整名稱),使用String
的compareTo()
方法進行對比,簡單說是根據字母序和字母長度進行排序,完成後,所有的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
}
}
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,所以上邊邏輯中只要leastWithNoSmallers
爲null
,那麼纔會觸發賦值。
@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
的關聯關係,實際上的調用的OrderComparator
的doCompare
方法,如下:
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;
}
通過上邊的分析,就可以瞭解最終是如何調用到切面類的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屬性的值,做一次排序,
這次排序不會更改之前同一個類型中切面方法的相對順序
- 根據上邊幾步的排序結果,依次觸發切面的邏輯