spring5 原始碼深度解析----- AOP代理的生成
在獲取了所有對應bean的增強後,便可以進行代理的建立了。回到AbstractAutoProxyCreator的wrapIfNecessary方法中,如下所示:
1 protected static final Object[] DO_NOT_PROXY = null; 2 3 protected Object wrapIfNecessary(Object bean, String beanName, Object cacheKey) { 4 if (StringUtils.hasLength(beanName) && this.targetSourcedBeans.contains(beanName)) { 5 return bean; 6 } 7 if (Boolean.FALSE.equals(this.advisedBeans.get(cacheKey))) { 8 return bean; 9 } 10 if (isInfrastructureClass(bean.getClass()) || shouldSkip(bean.getClass(), beanName)) { 11 this.advisedBeans.put(cacheKey, Boolean.FALSE); 12 return bean; 13 } 14 15 // Create proxy if we have advice. 16 Object[] specificInterceptors = getAdvicesAndAdvisorsForBean(bean.getClass(), beanName, null); 17 if (specificInterceptors != DO_NOT_PROXY) { 18 this.advisedBeans.put(cacheKey, Boolean.TRUE); 19 Object proxy = createProxy( 20 bean.getClass(), beanName, specificInterceptors, new SingletonTargetSource(bean)); 21 this.proxyTypes.put(cacheKey, proxy.getClass()); 22 return proxy; 23 } 24 25 this.advisedBeans.put(cacheKey, Boolean.FALSE); 26 return bean; 27 }
我們上一篇文章分析完了第16行,獲取到了所有對應bean的增強器,並獲取到了此目標bean所有匹配的 Advisor,接下來我們要從第17行開始分析,如果 specificInterceptors 不為空,則要為當前bean建立代理類,接下來我們來看建立代理類的方法 createProxy:
protected Object createProxy(Class<?> beanClass, @Nullable String beanName, @Nullable 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()) { // 決定對於給定的bean是否應該使用targetClass而不是他的介面代理, // 檢査 proxyTargetClass 設定以及 preserveTargetClass 屬性 if (shouldProxyTargetClass(beanClass, beanName)) { proxyFactory.setProxyTargetClass(true); } else { evaluateProxyInterfaces(beanClass, proxyFactory); } } Advisor[] advisors = buildAdvisors(beanName, specificInterceptors); // 加入增強器 proxyFactory.addAdvisors(advisors); // 設定要代理的目標類 proxyFactory.setTargetSource(targetSource); // 定製代理 customizeProxyFactory(proxyFactory); // 用來控制代理工廠被配置之後,是否還允許修改通知。 // 預設值是false (即在代理被配置之後,不允許修改代理的配置)。 proxyFactory.setFrozen(this.freezeProxy); if (advisorsPreFiltered()) { proxyFactory.setPreFiltered(true); } //真正建立代理的方法 return proxyFactory.getProxy(getProxyClassLoader()); } @Override public void setTargetSource(@Nullable TargetSource targetSource) { this.targetSource = (targetSource != null ? targetSource : EMPTY_TARGET_SOURCE); } public void addAdvisors(Collection<Advisor> advisors) { if (isFrozen()) { throw new AopConfigException("Cannot add advisor: Configuration is frozen."); } if (!CollectionUtils.isEmpty(advisors)) { for (Advisor advisor : advisors) { if (advisor instanceof IntroductionAdvisor) { validateIntroductionAdvisor((IntroductionAdvisor) advisor); } Assert.notNull(advisor, "Advisor must not be null"); this.advisors.add(advisor); } updateAdvisorArray(); adviceChanged(); } }
從上面程式碼我們看到對於代理類的建立及處理spring是委託給了ProxyFactory處理的
建立代理
public Object getProxy(@Nullable ClassLoader classLoader) { return createAopProxy().getProxy(classLoader); }
在上面的getProxy方法中createAopProxy方法,其實現是在DefaultAopProxyFactory中,這個方法的主要功能是,根據optimize、ProxyTargetClass等引數來決定生成Jdk動態代理,還是生成Cglib代理。我們進入到方法內:
protected final synchronized AopProxy createAopProxy() { if (!this.active) { activate(); } // 建立代理 return getAopProxyFactory().createAopProxy(this); } public AopProxy createAopProxy(AdvisedSupport config) throws AopConfigException { 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."); } //手動設定建立Cglib代理類後,如果目標bean是一個介面,也要建立jdk代理類 if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) { return new JdkDynamicAopProxy(config); } //建立Cglib代理 return new ObjenesisCglibAopProxy(config); } else { //預設建立jdk代理 return new JdkDynamicAopProxy(config); } }
我們知道對於Spring的代理是通過JDKProxy的實現和CglibProxy實現。Spring是如何選取的呢?
從if的判斷條件中可以看到3個方面影響這Spring的判斷。
-
optimize:用來控制通過CGLIB建立的代理是否使用激進的優化策略,除非完全瞭解AOP代理如何處理優化,否則不推薦使用者使用這個設定。目前這個屬性僅用於CGLIB 代理,對於JDK動態代理(預設代理)無效。
-
proxyTargetClass:這個屬性為true時,目標類本身被代理而不是目標類的介面。如果這個屬性值被設為true,CGLIB代理將被建立,設定方式:<aop:aspectj-autoproxy proxy-target-class="true"/>。
-
hasNoUserSuppliedProxylnterfaces:是否存在代理介面
下面是對JDK與Cglib方式的總結。
-
如果目標物件實現了介面,預設情況下會採用JDK的動態代理實現AOP。
-
如果目標物件實現了介面,可以強制使用CGLIB實現AOP。
-
如果目標物件沒有實現了介面,必須採用CGLIB庫,Spring會自動在JDK動態代理 和CGLIB之間轉換。
如何強制使用CGLIB實現AOP?
(1)新增 CGLIB 庫,Spring_HOME/cglib/*.jar。
(2)在 Spring 配置檔案中加人<aop:aspectj-autoproxy proxy-target-class="true"/>。
JDK動態代理和CGLIB位元組碼生成的區別?
- JDK動態代理只能對實現了介面的類生成代理,而不能針對類。
- CGLIB是針對類實現代理,主要是對指定的類生成一個子類,覆蓋其中的方法,因為是繼承,所以該類或方法最好不要宣告成final。
獲取代理
本文主要介紹JDK動態代理類的實現,在此之前,有必要熟悉一下JDK代理使用示例,請看我以前的博文,JDK動態代理原始碼分析文章《java基礎(十八)----- java動態代理原理原始碼解析》
Spring的AOP實現其實也是用了Proxy和InvocationHandler這兩個東西的。
我們再次來回顧一下使用JDK代理的方式,在整個建立過程中,對於InvocationHandler的建立是最為核心的,在自定義的InvocationHandler中需要重寫3個函式。
- 建構函式,將代理的物件傳入。
- invoke方法,此方法中實現了 AOP增強的所有邏輯。
- getProxy方法,此方法千篇一律,但是必不可少。
那麼,我們看看Spring中的JDK代理實現是不是也是這麼做的呢?我們來看看簡化後的 JdkDynamicAopProxy 。
1 final class JdkDynamicAopProxy implements AopProxy, InvocationHandler, Serializable { 2 3 private final AdvisedSupport advised; 4 5 public JdkDynamicAopProxy(AdvisedSupport config) throws AopConfigException { 6 Assert.notNull(config, "AdvisedSupport must not be null"); 7 if (config.getAdvisors().length == 0 && config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE) { 8 throw new AopConfigException("No advisors and no TargetSource specified"); 9 } 10 this.advised = config; 11 } 12 13 14 @Override 15 public Object getProxy() { 16 return getProxy(ClassUtils.getDefaultClassLoader()); 17 } 18 19 @Override 20 public Object getProxy(@Nullable ClassLoader classLoader) { 21 if (logger.isTraceEnabled()) { 22 logger.trace("Creating JDK dynamic proxy: " + this.advised.getTargetSource()); 23 } 24 Class<?>[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised, true); 25 findDefinedEqualsAndHashCodeMethods(proxiedInterfaces); 26 return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this); 27 } 28 29 @Override 30 @Nullable 31 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 32 Object oldProxy = null; 33 boolean setProxyContext = false; 34 35 TargetSource targetSource = this.advised.targetSource; 36 Object target = null; 37 38 try { 39 if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) { 40 // The target does not implement the equals(Object) method itself. 41 return equals(args[0]); 42 } 43 else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) { 44 // The target does not implement the hashCode() method itself. 45 return hashCode(); 46 } 47 else if (method.getDeclaringClass() == DecoratingProxy.class) { 48 // There is only getDecoratedClass() declared -> dispatch to proxy config. 49 return AopProxyUtils.ultimateTargetClass(this.advised); 50 } 51 else if (!this.advised.opaque && method.getDeclaringClass().isInterface() && 52 method.getDeclaringClass().isAssignableFrom(Advised.class)) { 53 // Service invocations on ProxyConfig with the proxy config... 54 return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args); 55 } 56 57 Object retVal; 58 59 if (this.advised.exposeProxy) { 60 // Make invocation available if necessary. 61 oldProxy = AopContext.setCurrentProxy(proxy); 62 setProxyContext = true; 63 } 64 65 // Get as late as possible to minimize the time we "own" the target, 66 // in case it comes from a pool. 67 target = targetSource.getTarget(); 68 Class<?> targetClass = (target != null ? target.getClass() : null); 69 70 // Get the interception chain for this method. 71 List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); 72 73 // Check whether we have any advice. If we don't, we can fallback on direct 74 // reflective invocation of the target, and avoid creating a MethodInvocation. 75 if (chain.isEmpty()) { 76 // We can skip creating a MethodInvocation: just invoke the target directly 77 // Note that the final invoker must be an InvokerInterceptor so we know it does 78 // nothing but a reflective operation on the target, and no hot swapping or fancy proxying. 79 Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args); 80 retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse); 81 } 82 else { 83 // We need to create a method invocation... 84 MethodInvocation invocation = 85 new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain); 86 // Proceed to the joinpoint through the interceptor chain. 87 retVal = invocation.proceed(); 88 } 89 90 // Massage return value if necessary. 91 Class<?> returnType = method.getReturnType(); 92 if (retVal != null && retVal == target && 93 returnType != Object.class && returnType.isInstance(proxy) && 94 !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) { 95 // Special case: it returned "this" and the return type of the method 96 // is type-compatible. Note that we can't help if the target sets 97 // a reference to itself in another returned object. 98 retVal = proxy; 99 } 100 else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) { 101 throw new AopInvocationException( 102 "Null return value from advice does not match primitive return type for: " + method); 103 } 104 return retVal; 105 } 106 finally { 107 if (target != null && !targetSource.isStatic()) { 108 // Must have come from TargetSource. 109 targetSource.releaseTarget(target); 110 } 111 if (setProxyContext) { 112 // Restore old proxy. 113 AopContext.setCurrentProxy(oldProxy); 114 } 115 } 116 } 117 118 }
我們看到JdkDynamicAopProxy 也是和我們自定義的InvocationHandler一樣,實現了InvocationHandler介面,並且提供了一個getProxy方法建立代理類,重寫invoke方法。
我們重點看看代理類的呼叫。瞭解Jdk動態代理的話都會知道,在實現Jdk動態代理功能,要實現InvocationHandler介面的invoke方法(這個方法是一個回撥方法)。 被代理類中的方法被呼叫時,實際上是呼叫的invoke方法,我們看一看這個方法的實現。
1 @Override 2 @Nullable 3 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 4 MethodInvocation invocation; 5 Object oldProxy = null; 6 boolean setProxyContext = false; 7 8 TargetSource targetSource = this.advised.targetSource; 9 Object target = null; 10 11 try { 12 if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) { 13 return equals(args[0]); 14 } 15 else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) { 16 return hashCode(); 17 } 18 else if (method.getDeclaringClass() == DecoratingProxy.class) { 19 return AopProxyUtils.ultimateTargetClass(this.advised); 20 } 21 else if (!this.advised.opaque && method.getDeclaringClass().isInterface() && 22 method.getDeclaringClass().isAssignableFrom(Advised.class)) { 23 return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args); 24 } 25 26 Object retVal; 27 if (this.advised.exposeProxy) { 28 // Make invocation available if necessary. 29 oldProxy = AopContext.setCurrentProxy(proxy); 30 setProxyContext = true; 31 } 32 33 target = targetSource.getTarget(); 34 Class<?> targetClass = (target != null ? target.getClass() : null); 35 36 // 獲取當前方法的攔截器鏈 37 List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); 38 39 if (chain.isEmpty()) { 40 // 如果沒有發現任何攔截器那麼直接呼叫切點方法 41 Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args); 42 retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse); 43 } 44 else { 45 // We need to create a method invocation... 46 // 將攔截器封裝在ReflectiveMethodInvocation, 47 // 以便於使用其proceed進行連結表用攔截器 48 invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain); 49 // Proceed to the joinpoint through the interceptor chain. 50 // 執行攔截器鏈 51 retVal = invocation.proceed(); 52 } 53 54 Class<?> returnType = method.getReturnType(); 55 // 返回結果 56 if (retVal != null && retVal == target && 57 returnType != Object.class && returnType.isInstance(proxy) && 58 !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) { 59 retVal = proxy; 60 } 61 else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) { 62 throw new AopInvocationException( 63 "Null return value from advice does not match primitive return type for: " + method); 64 } 65 return retVal; 66 } 67 finally { 68 if (target != null && !targetSource.isStatic()) { 69 // Must have come from TargetSource. 70 targetSource.releaseTarget(target); 71 } 72 if (setProxyContext) { 73 // Restore old proxy. 74 AopContext.setCurrentProxy(oldProxy); 75 } 76 } 77 }
我們先來看看第37行,獲取目標bean中目標method中的增強器,並將增強器封裝成攔截器鏈
1 @Override 2 public List<Object> getInterceptorsAndDynamicInterceptionAdvice( 3 Advised config, Method method, @Nullable Class<?> targetClass) { 4 5 // This is somewhat tricky... We have to process introductions first, 6 // but we need to preserve order in the ultimate list. 7 AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance(); 8 Advisor[] advisors = config.getAdvisors(); 9 List<Object> interceptorList = new ArrayList<>(advisors.length); 10 Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass()); 11 Boolean hasIntroductions = null; 12 13 //獲取bean中的所有增強器 14 for (Advisor advisor : advisors) { 15 if (advisor instanceof PointcutAdvisor) { 16 // Add it conditionally. 17 PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor; 18 if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) { 19 MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher(); 20 boolean match; 21 if (mm instanceof IntroductionAwareMethodMatcher) { 22 if (hasIntroductions == null) { 23 hasIntroductions = hasMatchingIntroductions(advisors, actualClass); 24 } 25 match = ((IntroductionAwareMethodMatcher) mm).matches(method, actualClass, hasIntroductions); 26 } 27 else { 28 //根據增強器中的Pointcut判斷增強器是否能匹配當前類中的method 29 //我們要知道目標Bean中並不是所有的方法都需要增強,也有一些普通方法 30 match = mm.matches(method, actualClass); 31 } 32 if (match) { 33 //如果能匹配,就將advisor封裝成MethodInterceptor加入到interceptorList中 34 MethodInterceptor[] interceptors = registry.getInterceptors(advisor); 35 if (mm.isRuntime()) { 36 // Creating a new object instance in the getInterceptors() method 37 // isn't a problem as we normally cache created chains. 38 for (MethodInterceptor interceptor : interceptors) { 39 interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm)); 40 } 41 } 42 else { 43 interceptorList.addAll(Arrays.asList(interceptors)); 44 } 45 } 46 } 47 } 48 else if (advisor instanceof IntroductionAdvisor) { 49 IntroductionAdvisor ia = (IntroductionAdvisor) advisor; 50 if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) { 51 Interceptor[] interceptors = registry.getInterceptors(advisor); 52 interceptorList.addAll(Arrays.asList(interceptors)); 53 } 54 } 55 else { 56 Interceptor[] interceptors = registry.getInterceptors(advisor); 57 interceptorList.addAll(Arrays.asList(interceptors)); 58 } 59 } 60 61 return interceptorList; 62 }
我們知道目標Bean中並不是所有的方法都需要增強,所以我們要遍歷所有的 Advisor ,根據Pointcut判斷增強器是否能匹配當前類中的method,取出能匹配的增強器,封裝成 MethodInterceptor,加入到攔截器鏈中,我們來看看第34行
@Override public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException { List<MethodInterceptor> interceptors = new ArrayList<>(3); Advice advice = advisor.getAdvice(); if (advice instanceof MethodInterceptor) { interceptors.add((MethodInterceptor) advice); } //這裡遍歷三個介面卡,將對應的advisor轉化成Interceptor //這三個介面卡分別是MethodBeforeAdviceAdapter,AfterReturningAdviceAdapter,ThrowsAdviceAdapter for (AdvisorAdapter adapter : this.adapters) { if (adapter.supportsAdvice(advice)) { interceptors.add(adapter.getInterceptor(advisor)); } } if (interceptors.isEmpty()) { throw new UnknownAdviceTypeException(advisor.getAdvice()); } return interceptors.toArray(new MethodInterceptor[0]); } private final List<AdvisorAdapter> adapters = new ArrayList<>(3); /** * Create a new DefaultAdvisorAdapterRegistry, registering well-known adapters. */ public DefaultAdvisorAdapterRegistry() { registerAdvisorAdapter(new MethodBeforeAdviceAdapter()); registerAdvisorAdapter(new AfterReturningAdviceAdapter()); registerAdvisorAdapter(new ThrowsAdviceAdapter()); } @Override public void registerAdvisorAdapter(AdvisorAdapter adapter) { this.adapters.add(adapter); }
由於Spring中涉及過多的攔截器,增強器,增強方法等方式來對邏輯進行增強,在上一篇文章中我們知道建立的幾個增強器,AspectJAroundAdvice、AspectJAfterAdvice、AspectJAfterThrowingAdvice這幾個增強器都實現了 MethodInterceptor 介面,AspectJMethodBeforeAdvice 和AspectJAfterReturningAdvice 並沒有實現 MethodInterceptor 介面,因此AspectJMethodBeforeAdvice 和AspectJAfterReturningAdvice不能滿足MethodInterceptor 介面中的invoke方法,所以這裡使用介面卡模式將AspectJMethodBeforeAdvice 和AspectJAfterReturningAdvice轉化成能滿足需求的MethodInterceptor實現類。
遍歷adapters,通過adapter.supportsAdvice(advice)找到advice對應的介面卡,adapter.getInterceptor(advisor)將advisor轉化成對應的interceptor
我們來看看這幾個增強器
AspectJAroundAdvice
public class AspectJAroundAdvice extends AbstractAspectJAdvice implements MethodInterceptor, Serializable { public AspectJAroundAdvice( Method aspectJAroundAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) { super(aspectJAroundAdviceMethod, pointcut, aif); } @Override public boolean isBeforeAdvice() { return false; } @Override public boolean isAfterAdvice() { return false; } @Override public Object invoke(MethodInvocation mi) throws Throwable { if (!(mi instanceof ProxyMethodInvocation)) { throw new IllegalStateException("MethodInvocation is not a Spring ProxyMethodInvocation: " + mi); } ProxyMethodInvocation pmi = (ProxyMethodInvocation) mi; ProceedingJoinPoint pjp = lazyGetProceedingJoinPoint(pmi); JoinPointMatch jpm = getJoinPointMatch(pmi); return invokeAdviceMethod(pjp, jpm, null, null); } }View Code
AspectJMethodBeforeAdvice
public class AspectJMethodBeforeAdvice extends AbstractAspectJAdvice implements MethodBeforeAdvice, Serializable { public AspectJMethodBeforeAdvice( Method aspectJBeforeAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) { super(aspectJBeforeAdviceMethod, pointcut, aif); } @Override public void before(Method method, Object[] args, @Nullable Object target) throws Throwable { invokeAdviceMethod(getJoinPointMatch(), null, null); } @Override public boolean isBeforeAdvice() { return true; } @Override public boolean isAfterAdvice() { return false; } }View Code
AspectJAfterAdvice
public class AspectJAfterAdvice extends AbstractAspectJAdvice implements MethodInterceptor, AfterAdvice, Serializable { public AspectJAfterAdvice( Method aspectJBeforeAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) { super(aspectJBeforeAdviceMethod, pointcut, aif); } @Override public Object invoke(MethodInvocation mi) throws Throwable { try { return mi.proceed(); } finally { invokeAdviceMethod(getJoinPointMatch(), null, null); } } @Override public boolean isBeforeAdvice() { return false; } @Override public boolean isAfterAdvice() { return true; } }View Code
AspectJAfterReturningAdvice
public class AspectJAfterReturningAdvice extends AbstractAspectJAdvice implements AfterReturningAdvice, AfterAdvice, Serializable { public AspectJAfterReturningAdvice( Method aspectJBeforeAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) { super(aspectJBeforeAdviceMethod, pointcut, aif); } @Override public boolean isBeforeAdvice() { return false; } @Override public boolean isAfterAdvice() { return true; } @Override public void afterReturning(@Nullable Object returnValue, Method method, Object[] args, @Nullable Object target) throws Throwable { if (shouldInvokeOnReturnValueOf(method, returnValue)) { invokeAdviceMethod(getJoinPointMatch(), returnValue, null); } } }View Code
AspectJAfterThrowingAdvice
public class AspectJAfterThrowingAdvice extends AbstractAspectJAdvice implements MethodInterceptor, AfterAdvice, Serializable { public AspectJAfterThrowingAdvice( Method aspectJBeforeAdviceMethod, AspectJExpressionPointcut pointcut, AspectInstanceFactory aif) { super(aspectJBeforeAdviceMethod, pointcut, aif); } @Override public boolean isBeforeAdvice() { return false; } @Override public boolean isAfterAdvice() { return true; } @Override public Object invoke(MethodInvocation mi) throws Throwable { try { return mi.proceed(); } catch (Throwable ex) { if (shouldInvokeOnThrowing(ex)) { invokeAdviceMethod(getJoinPointMatch(), null, ex); } throw ex; } } }View Code
接下來我們看看MethodBeforeAdviceAdapter和AfterReturningAdviceAdapter這兩個介面卡,這兩個介面卡是將MethodBeforeAdvice和AfterReturningAdvice適配成對應的Interceptor
MethodBeforeAdviceAdapter
class MethodBeforeAdviceAdapter implements AdvisorAdapter, Serializable { @Override public boolean supportsAdvice(Advice advice) { //判斷是否是MethodBeforeAdvice型別的advice return (advice instanceof MethodBeforeAdvice); } @Override public MethodInterceptor getInterceptor(Advisor advisor) { MethodBeforeAdvice advice = (MethodBeforeAdvice) advisor.getAdvice(); //將advice封裝成MethodBeforeAdviceInterceptor return new MethodBeforeAdviceInterceptor(advice); } } //MethodBeforeAdviceInterceptor實現了MethodInterceptor介面,實現了invoke方法,並將advice作為屬性 public class MethodBeforeAdviceInterceptor implements MethodInterceptor, BeforeAdvice, Serializable { private final MethodBeforeAdvice advice; public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) { Assert.notNull(advice, "Advice must not be null"); this.advice = advice; } @Override public Object invoke(MethodInvocation mi) throws Throwable { this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis()); return mi.proceed(); } }
AfterReturningAdviceAdapter
class AfterReturningAdviceAdapter implements AdvisorAdapter, Serializable { @Override public boolean supportsAdvice(Advice advice) { return (advice instanceof AfterReturningAdvice); } @Override public MethodInterceptor getInterceptor(Advisor advisor) { AfterReturningAdvice advice = (AfterReturningAdvice) advisor.getAdvice(); return new AfterReturningAdviceInterceptor(advice); } } public class AfterReturningAdviceInterceptor implements MethodInterceptor, AfterAdvice, Serializable { private final AfterReturningAdvice advice; public AfterReturningAdviceInterceptor(AfterReturningAdvice advice) { Assert.notNull(advice, "Advice must not be null"); this.advice = advice; } @Override public Object invoke(MethodInvocation mi) throws Throwable { Object retVal = mi.proceed(); this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis()); return retVal; } }
至此我們獲取到了一個攔截器鏈,鏈中包括AspectJAroundAdvice、AspectJAfterAdvice、AspectJAfterThrowingAdvice、MethodBeforeAdviceInterceptor、AfterReturningAdviceInterceptor
接下來 ReflectiveMethodInvocation 類進行了鏈的封裝,而在ReflectiveMethodInvocation類的proceed方法中實現了攔截器的逐一呼叫,那麼我們繼續來探究,在proceed方法中是怎麼實現前置增強在目標方法前呼叫後置增強在目標方法後呼叫的邏輯呢?
我們先來看看ReflectiveMethodInvocation的構造器,只是簡單的進行屬性賦值,不過我們要注意有一個特殊的變數currentInterceptorIndex,這個變數代表執行Interceptor的下標,從-1開始,Interceptor執行一個,先++this.currentInterceptorIndex
protected ReflectiveMethodInvocation( Object proxy, @Nullable Object target, Method method, @Nullable Object[] arguments, @Nullable Class<?> targetClass, List<Object> interceptorsAndDynamicMethodMatchers) { this.proxy = proxy; this.target = target; this.targetClass = targetClass; this.method = BridgeMethodResolver.findBridgedMethod(method); this.arguments = AopProxyUtils.adaptArgumentsIfNecessary(method, arguments); this.interceptorsAndDynamicMethodMatchers = interceptorsAndDynamicMethodMatchers; } private int currentInterceptorIndex = -1;
下面是ReflectiveMethodInvocation類Proceed方法:
public Object proceed() throws Throwable { // 首先,判斷是不是所有的interceptor(也可以想像成advisor)都被執行完了。 // 判斷的方法是看currentInterceptorIndex這個變數的值,增加到Interceptor總個數這個數值沒有, // 如果到了,就執行被代理方法(invokeJoinpoint());如果沒到,就繼續執行Interceptor。 if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) { return invokeJoinpoint(); } // 如果Interceptor沒有被全部執行完,就取出要執行的Interceptor,並執行。 // currentInterceptorIndex先自增 Object interceptorOrInterceptionAdvice =this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex); // 如果Interceptor是PointCut型別 if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) { InterceptorAndDynamicMethodMatcher dm = (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice; // 如果當前方法符合Interceptor的PointCut限制,就執行Interceptor if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) { // 這裡將this當變數傳進去,這是非常重要的一點 return dm.interceptor.invoke(this); } // 如果不符合,就跳過當前Interceptor,執行下一個Interceptor else { return proceed(); } } // 如果Interceptor不是PointCut型別,就直接執行Interceptor裡面的增強。 else { return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this); } }
由於篇幅過程,目標方法和增強方法是如何執行的,我們將重新寫一篇文章來講解
&n