1. 背景
在前文Spring IOC容器創建bean過程淺析已經介紹了Spring IOC創建初始化bean的大致過程。現在對Spring的AOP實現機制進行研究分析。
2. 名詞與概念
名詞 | 概念 |
---|---|
Advice | 通知,在連接點的處理邏輯 |
Advisor | Advisor可以簡單理解為Advice+PointCut |
Interceptor | 攔截器 |
Aspect | 切面 |
3. 代理類創建的入口--AbstractAutoProxyCreator
AbstractAutoProxyCreator是Spring AOP實現的一個很重要的抽象類。下面是它的繼承層次。
我們可以注意到,它其實是一個BeanPostProcessor。我們需要重點關注的方法是其中的wrapIfNecessary方法,可以說這是Spring實現Bean代理的核心方法。
wrapIfNecessary在兩處會被調用,一處是getEarlyBeanReference,另一處是postProcessAfterInitialization。
protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) {
if (beanName != null && this.targetSourcedBeans.contains(beanName)) {
return bean;
}
// 判斷是否不應該代理這個bean。
if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) {
return bean;
}
/*
* 判斷是否是一些InfrastructureClass或者是否應該跳過這個bean。
* 所謂InfrastructureClass就是指Advice/PointCut/Advisor等接口的實現類。
* shouldSkip默認實現為返回false,由於是protected方法,子類可以覆蓋。
*/
if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) {
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
// 獲取這個bean的advice。
Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null);
if (specificInterceptors != DO_NOT_PROXY) {
this.advisedBeans.put(cacheKey, Boolean.TRUE);
// 創建代理。
Object proxy = createProxy(
bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean));
this.proxyTypes.put(cacheKey, proxy.getClass());
return proxy;
}
// 這個bean不需要被代理。
this.advisedBeans.put(cacheKey, Boolean.FALSE);
return bean;
}
protected Object createProxy(
Class<?> beanClass, String beanName, Object[] specificInterceptors, TargetSource targetSource) {
if (this.beanFactory instanceof ConfigurableListableBeanFactory) {
AutoProxyUtils.exposeTargetClass((ConfigurableListableBeanFactory) this.beanFactory, beanName, beanClass);
}
ProxyFactory proxyFactory = new ProxyFactory();
proxyFactory.copyFrom(this);
if (!proxyFactory.isProxyTargetClass()) {
if (shouldProxyTargetClass(beanClass, beanName)) {
proxyFactory.setProxyTargetClass(true);
}
else {
evaluateProxyInterfaces(beanClass, proxyFactory);
}
}
Advisor[] advisors = buildAdvisors(beanName, specificInterceptors);
for (Advisor advisor : advisors) {
proxyFactory.addAdvisor(advisor);
}
proxyFactory.setTargetSource(targetSource);
customizeProxyFactory(proxyFactory);
proxyFactory.setFrozen(this.freezeProxy);
if (advisorsPreFiltered()) {
proxyFactory.setPreFiltered(true);
}
return proxyFactory.getProxy(getProxyClassLoader());
}
4. 代理類創建的實現
從上面的createProxy方法中,我們可以看到,最終Spring是通過ProxyFactory#getProxy的調用來獲取最終的代理bean的。
下面就來看一下這其中的過程。
public Object getProxy(ClassLoader classLoader) {
return createAopProxy().getProxy(classLoader);
}
/**
* 該方法是ProxyCreatorSupport(ProxyFactory的基類)的保護方法。
*/
protected final synchronized AopProxy createAopProxy() {
if (!this.active) {
activate();
}
return getAopProxyFactory().createAopProxy(this);
}
DefaultAopProxyFactory是AopProxyFactory接口的默認實現,下面來看一下其中createAopProxy方法的實現。Spring就是在這里判斷是使用JDK動態代理還是cglib代理的。
public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException {
/*
* 這里是Spring判斷是用JDK動態代理還是Cglib代理的依據。
* 1. optimize開關被設置為true。此開關默認為false。
* 2. proxyTargetClass開關為true。
* 3. 沒有用戶代理接口。所謂用戶代理接口就是指非Spring生成的代理。
*
* 滿足上述三點任意一點就會根據代理類本身
*/
if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) {
Class<?> targetClass = config.getTargetClass();
if (targetClass == null) {
throw new AopConfigException("TargetSource cannot determine target class: " +
"Either an interface or a target is required for proxy creation.");
}
// 如果targetClass本身是個接口或者targetClass是JDK Proxy生成的,則使用JDK動態代理。
if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) {
return new JdkDynamicAopProxy(config);
}
// 否則使用Cglib代理。
return new ObjenesisCglibAopProxy(config);
}
else {
// 使用JDK動態代理。
return new JdkDynamicAopProxy(config);
}
}
4.1 JDK動態代理--JdkDynamicAopProxy的源碼分析
public Object getProxy(ClassLoader classLoader) {
if (logger.isDebugEnabled()) {
logger.debug("Creating JDK dynamic proxy: target source is " + this.advised.getTargetSource());
}
Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true);
findDefinedEqualsAndHashCodeMethods(proxiedInterfaces);
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
}
可以看到本質上JdkDynamicAopProxy對於AopProxy的getProxy方法的實現本質上是調用我們熟悉的Proxy.newProxyInstance來生成代理bean。
而JdkDynamicAopProxy本身也實現了InvocationHandler接口。下面就來看下它對InvocationHandler#invoke的實現。
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
MethodInvocation invocation;
Object oldProxy = null;
boolean setProxyContext = false;
TargetSource targetSource = this.advised.targetSource;
Class<?> targetClass = null;
Object target = null;
try {
if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
// 方法為equals且代理bean本身沒有實現equals方法。
return equals(args[0]);
}
else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
// 方法為hashCode且代理bean本身沒有實現hashCode方法。
return hashCode();
}
else if (method.getDeclaringClass() == DecoratingProxy.class) {
return AopProxyUtils.ultimateTargetClass(this.advised);
}
else if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
method.getDeclaringClass().isAssignableFrom(Advised.class)) {
return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
}
Object retVal;
if (this.advised.exposeProxy) {
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
target = targetSource.getTarget();
if (target != null) {
targetClass = target.getClass();
}
// 獲取該方法對應的攔截器鏈。
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
// 如果沒有任何攔截器,則通過反射調用對應方法。
if (chain.isEmpty()) {
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse);
}
else {
// 創建方法調用鏈。
invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
// 調用方法聯。
retVal = invocation.proceed();
}
Class<?> returnType = method.getReturnType();
// 如果返回的是this,則判斷是否需要把retVal設置為代理對象。
if (retVal != null && retVal == target &&
returnType != Object.class && returnType.isInstance(proxy) &&
!RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
retVal = proxy;
}
else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
throw new AopInvocationException(
"Null return value from advice does not match primitive return type for: " + method);
}
return retVal;
}
finally {
if (target != null && !targetSource.isStatic()) {
targetSource.releaseTarget(target);
}
if (setProxyContext) {
AopContext.setCurrentProxy(oldProxy);
}
}
}
4.2 cglib代理--CglibAopProxy的源碼分析
Spring對於cglib創建代理,內部默認使用ObjenesisCglibAopProxy來創建代理bean,它是CglibAopProxy的子類,並且重寫了createProxyClassAndInstance方法。Objenesis是一個類庫,可以繞過構造器創建對象。
cglib使用Enhancer來生成代理類,生成的類實質上是被代理類的子類。更多關於Enhancer的信息,可以參考我的博文cglib之Enhancer。
public Object getProxy(ClassLoader classLoader) {
if (logger.isDebugEnabled()) {
logger.debug("Creating CGLIB proxy: target source is " + this.advised.getTargetSource());
}
try {
// advised其實就是創建CglibAopProxy的時候構造參數中傳遞的config配置。
Class<?> rootClass = this.advised.getTargetClass();
Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");
Class<?> proxySuperClass = rootClass;
if (ClassUtils.isCglibProxyClass(rootClass)) {
proxySuperClass = rootClass.getSuperclass();
Class<?>[] additionalInterfaces = rootClass.getInterfaces();
for (Class<?> additionalInterface : additionalInterfaces) {
this.advised.addInterface(additionalInterface);
}
}
validateClassIfNecessary(proxySuperClass, classLoader);
Enhancer enhancer = createEnhancer();
if (classLoader != null) {
enhancer.setClassLoader(classLoader);
if (classLoader instanceof SmartClassLoader &&
((SmartClassLoader) classLoader).isClassReloadable(proxySuperClass)) {
enhancer.setUseCache(false);
}
}
// 配置enhancer如代理接口,回調等。
enhancer.setSuperclass(proxySuperClass);
enhancer.setInterfaces(AopProxyUtils.completeProxiedInterfaces(this.advised));
enhancer.setNamingPolicy(SpringNamingPolicy.INSTANCE);
enhancer.setStrategy(new ClassLoaderAwareUndeclaredThrowableStrategy(classLoader));
// 這里生成callback方法的邏輯是閱讀源碼的重點。
Callback[] callbacks = getCallbacks(rootClass);
Class<?>[] types = new Class<?>[callbacks.length];
for (int x = 0; x < types.length; x++) {
types[x] = callbacks[x].getClass();
}
// callbackFilter的作用主要是建立了method與callback編號的映射。
enhancer.setCallbackFilter(new ProxyCallbackFilter(
this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset));
enhancer.setCallbackTypes(types);
// 生成代理的class以及代理bean實例。
return createProxyClassAndInstance(enhancer, callbacks);
}
catch (CodeGenerationException ex) {
throw new AopConfigException("Could not generate CGLIB subclass of class [" +
this.advised.getTargetClass() + "]: " +
"Common causes of this problem include using a final class or a non-visible class",
ex);
}
catch (IllegalArgumentException ex) {
throw new AopConfigException("Could not generate CGLIB subclass of class [" +
this.advised.getTargetClass() + "]: " +
"Common causes of this problem include using a final class or a non-visible class",
ex);
}
catch (Exception ex) {
throw new AopConfigException("Unexpected AOP exception", ex);
}
}
4.2.1 CglibAopProxy生成callbacks
在CglibAopProxy內部定義了一組常量用於表示生成的callback索引。
- AOP_PROXY = 0
一般的aop調用 - INVOKE_TARGET = 1
直接調用目標方法 - NO_OVERRIDE = 2
不能覆蓋的方法,比如finalize方法。 - DISPATCH_TARGET = 3
直接對原來的bean進行方法調用。 - DISPATCH_ADVISED = 4
對Advised接口方法有效 - INVOKE_EQUALS = 5
對equals方法攔截 - INVOKE_HASHCODE = 6
對hashCode方法攔截
接下來就看一下這些callback生成的具體源碼實現。
private Callback[] getCallbacks(Class<?> rootClass) throws Exception {
// Parameters used for optimisation choices...
boolean exposeProxy = this.advised.isExposeProxy();
boolean isFrozen = this.advised.isFrozen();
boolean isStatic = this.advised.getTargetSource().isStatic();
// 對於AOP方法的調用,使用DynamicAdvisedInterceptor攔截器。
Callback aopInterceptor = new DynamicAdvisedInterceptor(this.advised);
/*
* 不需要增強,但可能會返回this的方法:
* 如果targetSource是靜態的話(每次getTarget都是同一個對象),使用StaticUnadvisedExposedInterceptor
* 否則使用DynamicUnadvisedExposedInterceptor。
*
*/
Callback targetInterceptor;
if (exposeProxy) {
targetInterceptor = isStatic ?
new StaticUnadvisedExposedInterceptor(this.advised.getTargetSource().getTarget()) :
new DynamicUnadvisedExposedInterceptor(this.advised.getTargetSource());
}
/*
* 這里的分支邏輯與上面相同,只不過exposeProxy為false的情況下不會設置AopContext中的currentProxy。
*/
else {
targetInterceptor = isStatic ?
new StaticUnadvisedInterceptor(this.advised.getTargetSource().getTarget()) :
new DynamicUnadvisedInterceptor(this.advised.getTargetSource());
}
Callback targetDispatcher = isStatic ?
new StaticDispatcher(this.advised.getTargetSource().getTarget()) : new SerializableNoOp();
Callback[] mainCallbacks = new Callback[] {
// AOP攔截器。
aopInterceptor,
targetInterceptor,
new SerializableNoOp(),
targetDispatcher, this.advisedDispatcher,
new EqualsInterceptor(this.advised),
new HashCodeInterceptor(this.advised)
};
Callback[] callbacks;
/*
* 如果targetSource為靜態並且配置已經凍結(advice不會改變),可以封裝到FixedChainStaticTargetInterceptor來攔截調用方法。
* 其實FixedChainStaticTargetInterceptor里的邏輯就相當於對固定的target每次創建CglibMethodInvocation來實現aop攔截。
*/
if (isStatic && isFrozen) {
Method[] methods = rootClass.getMethods();
Callback[] fixedCallbacks = new Callback[methods.length];
this.fixedInterceptorMap = new HashMap<String, Integer>(methods.length);
for (int x = 0; x < methods.length; x++) {
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(methods[x], rootClass);
fixedCallbacks[x] = new FixedChainStaticTargetInterceptor(
chain, this.advised.getTargetSource().getTarget(), this.advised.getTargetClass());
this.fixedInterceptorMap.put(methods[x].toString(), x);
}
// 把mainCallbacks和fixedCallbacks拼起來。
callbacks = new Callback[mainCallbacks.length + fixedCallbacks.length];
System.arraycopy(mainCallbacks, 0, callbacks, 0, mainCallbacks.length);
System.arraycopy(fixedCallbacks, 0, callbacks, mainCallbacks.length, fixedCallbacks.length);
this.fixedInterceptorOffset = mainCallbacks.length;
}
else {
callbacks = mainCallbacks;
}
return callbacks;
}
4.2.2 CglibAopProxy的CallbackFilter
我們這里主要看ProxyCallbackFilter#accept方法的源碼實現。
public int accept(Method method) {
// finalize方法使用SerializableNoOp
if (AopUtils.isFinalizeMethod(method)) {
logger.debug("Found finalize() method - using NO_OVERRIDE");
return NO_OVERRIDE;
}
if (!this.advised.isOpaque() && method.getDeclaringClass().isInterface() &&
method.getDeclaringClass().isAssignableFrom(Advised.class)) {
if (logger.isDebugEnabled()) {
logger.debug("Method is declared on Advised interface: " + method);
}
return DISPATCH_ADVISED;
}
// equals方法使用EqualsInterceptor。
if (AopUtils.isEqualsMethod(method)) {
logger.debug("Found 'equals' method: " + method);
return INVOKE_EQUALS;
}
// hashCode方法使用HashCodeInterceptor。
if (AopUtils.isHashCodeMethod(method)) {
logger.debug("Found 'hashCode' method: " + method);
return INVOKE_HASHCODE;
}
Class<?> targetClass = this.advised.getTargetClass();
List<?> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
boolean haveAdvice = !chain.isEmpty();
boolean exposeProxy = this.advised.isExposeProxy();
boolean isStatic = this.advised.getTargetSource().isStatic();
boolean isFrozen = this.advised.isFrozen();
if (haveAdvice || !isFrozen) {
// 有advice,配置沒有凍結,且需要暴露proxy,使用DynamicAdvisedInterceptor。
if (exposeProxy) {
if (logger.isDebugEnabled()) {
logger.debug("Must expose proxy on advised method: " + method);
}
return AOP_PROXY;
}
String key = method.toString();
// 如果滿足優化條件(targetSource靜態且配置凍結),則嘗試使用fixedInterceptor。
if (isStatic && isFrozen && this.fixedInterceptorMap.containsKey(key)) {
if (logger.isDebugEnabled()) {
logger.debug("Method has advice and optimisations are enabled: " + method);
}
// 從fixedInterceptorMap中拿到編號加上偏移量即可。
int index = this.fixedInterceptorMap.get(key);
return (index + this.fixedInterceptorOffset);
}
else {
if (logger.isDebugEnabled()) {
logger.debug("Unable to apply any optimisations to advised method: " + method);
}
return AOP_PROXY;
}
}
else {
/*
* 如果需要暴露proxy或者targetSource非靜態,則使用的callback可能是下面三種之一。
* StaticUnadvisedExposedInterceptor
* DynamicUnadvisedExposedInterceptor
* DynamicUnadvisedInterceptor
*/
if (exposeProxy || !isStatic) {
return INVOKE_TARGET;
}
Class<?> returnType = method.getReturnType();
// 返回的類型與targetClass一致(有可能返回this),使用StaticUnadvisedInterceptor。
if (targetClass == returnType) {
if (logger.isDebugEnabled()) {
logger.debug("Method " + method +
"has return type same as target type (may return this) - using INVOKE_TARGET");
}
return INVOKE_TARGET;
}
// 返回類型為基本類型或者targetClass不兼容於返回類型(不可能返回this),使用StaticDispatcher。
else if (returnType.isPrimitive() || !returnType.isAssignableFrom(targetClass)) {
if (logger.isDebugEnabled()) {
logger.debug("Method " + method +
" has return type that ensures this cannot be returned- using DISPATCH_TARGET");
}
return DISPATCH_TARGET;
}
else {
// 這種情況targetClass是返回類型的子類(可能返回this),使用StaticUnadvisedInterceptor。
if (logger.isDebugEnabled()) {
logger.debug("Method " + method +
"has return type that is assignable from the target type (may return this) - " +
"using INVOKE_TARGET");
}
return INVOKE_TARGET;
}
}
}
4.2.3 CglibAopProxy的AOP方法攔截器--DynamicAdvisedInterceptor
在spring中通過cglib創建的代理中,對於需要增強的方法設置的callback為DynamicAdvisedInterceptor,它實現了cglib的MethodInterceptor。
private static class DynamicAdvisedInterceptor implements MethodInterceptor, Serializable {
private final AdvisedSupport advised;
public DynamicAdvisedInterceptor(AdvisedSupport advised) {
this.advised = advised;
}
@Override
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy) throws Throwable {
Object oldProxy = null;
boolean setProxyContext = false;
Class<?> targetClass = null;
Object target = null;
try {
if (this.advised.exposeProxy) {
// Make invocation available if necessary.
oldProxy = AopContext.setCurrentProxy(proxy);
setProxyContext = true;
}
// 拿出原始bean對象。
target = getTarget();
if (target != null) {
targetClass = target.getClass();
}
// 根據method和class從配置中獲取增強。
List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);
Object retVal;
// 如果沒有增強並且方法為public,則直接調用。
if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) {
Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args);
retVal = methodProxy.invoke(target, argsToUse);
}
else {
// 創建攔截器鏈並調用。
retVal = new CglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed();
}
retVal = processReturnType(proxy, target, method, retVal);
return retVal;
}
finally {
if (target != null) {
releaseTarget(target);
}
if (setProxyContext) {
// Restore old proxy.
AopContext.setCurrentProxy(oldProxy);
}
}
}
@Override
public boolean equals(Object other) {
return (this == other ||
(other instanceof DynamicAdvisedInterceptor &&
this.advised.equals(((DynamicAdvisedInterceptor) other).advised)));
}
@Override
public int hashCode() {
return this.advised.hashCode();
}
protected Object getTarget() throws Exception {
return this.advised.getTargetSource().getTarget();
}
protected void releaseTarget(Object target) throws Exception {
this.advised.getTargetSource().releaseTarget(target);
}
}
4.3 ReflectiveMethodInvocation#proceed
這里來看一下方法攔截器的具體實現。這個類特別重要,它是JDK動態代理和cglib代理底層都會用到的類,也就是作用在方法上的增強鏈的本質。
public Object proceed() throws Throwable {
// 邊界判斷,如果攔截器都調用完畢了就調用連接點方法。
if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
return invokeJoinpoint();
}
// 迭代攔截器聯獲取當前的攔截器。
Object interceptorOrInterceptionAdvice =
this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
InterceptorAndDynamicMethodMatcher dm =
(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
// 判斷是否和當前的切點匹配。
if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {
return dm.interceptor.invoke(this);
}
else {
// 如果不匹配的話,就遞歸調用proceed。
return proceed();
}
}
else {
// 如果是一個MethodInterceptor的話則直接調用。
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
5. 思考
為什么cglib創建的代理方法內部互相調用不會進入代理
這是個很常見的問題,比如會有疑問為什么一個非事務方法調用事務方法沒有進入事務等等。下面通過源碼來分析原因。
通過查看源碼可以看到,Spring的cglib的AOP無論方法是否有增強,本質上都是對target
進行調用。這里的target對於一般的AOP通常都是來源於
AbstractAutoProxyCreator#wrapIfNecessary中通過SingletonTargetSource包裝的入參bean,而不是cglib中實際生成的proxy對象。也就是說很可能target就是一個很朴素的bean。那么進入到這樣一個bean中的方法自然不會再觸發cglib代理的callback攔截了。
其實可以將代理看作是一個外殼,在方法被調用的時候會被攔截進入到殼子中寫好的邏輯,但是方法體本身已經脫離了外殼層,是在本體中運行的。
攔截器的順序問題
這個問題也是經常會困擾的問題,就是關於那些各種aop切方法,到底哪個會先切,哪個后切。
AbstractAutoProxyCreator#wrapIfNecessary中getAdvicesAndAdvisorsForBean用來抓取advice和advisor。
我們以AbstractAdvisorAutoProxyCreator#getAdvicesAndAdvisorsForBean的實現為例:
注意到這其中是有排序的邏輯的,以AspectJAwareAdvisorAutoProxyCreator#sortAdvisors為例可以看到用的comparator是內置的默認比較器AspectJPrecedenceComparator。
不妨再看一下AspectJPrecedenceComparator的比較策略:
可以看到會先使用內部的AnnotationAwareOrderComparator來比較,如果優先級相同,則再調用comparePrecedenceWithinAspect進行比較。
AnnotationAwareOrderComparator繼承自OrderComparator, 在OrderComparator中的判斷順序邏輯是如果任一對象是PriorityOrder接口的子類型,則具有更高優先級。否則調用getOrder方法比較。
注意,上面的排序規則只是影響了各advice的調用順序,並不代表我們關注的aop實際邏輯的調用順序,比如AspectJAfterAdvice#invoke也是先對methodInvocation調用proceed再處理本身的后置邏輯。