前面我們分析了Spring AOP實(shí)現中得到Proxy對象的過(guò)程,下面我們看看在Spring AOP中攔截器鏈是怎樣被調用的,也就是Proxy模式是怎樣起作用的,或者說(shuō)Spring是怎樣為我們提供AOP功能的;
在JdkDynamicAopProxy中生成Proxy對象的時(shí)候:
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
這里的this參數對應的是InvocationHandler對象,這里我們的JdkDynamicAopProxy實(shí)現了這個(gè)接口,也就是說(shuō)當Proxy對象的函數被調用的時(shí)候,這個(gè)InvocationHandler的invoke方法會(huì )被作為回調函數調用,下面我們看看這個(gè)方法的實(shí)現:
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {MethodInvocation invocation = null;Object oldProxy = null;boolean setProxyContext = false;TargetSource targetSource = this.advised.targetSource;Class targetClass = null;Object target = null;try {// Try special rules for equals() method and implementation of the// Advised AOP configuration interface.if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {// What if equals throws exception!?// This class implements the equals(Object) method itself.return equals(args[0]) ? Boolean.TRUE : Boolean.FALSE;}if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {// This class implements the hashCode() method itself.return new Integer(hashCode());}if (Advised.class == method.getDeclaringClass()) {// service invocations on ProxyConfig with the proxy configreturn AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);}Object retVal = null;if (this.advised.exposeProxy) {// make invocation available if necessaryoldProxy = AopContext.setCurrentProxy(proxy);setProxyContext = true;}// May be <code>null</code>. Get as late as possible to minimize the time we "own" the target,// in case it comes from a pool.// 這里是得到目標對象的地方,當然這個(gè)目標對象可能來(lái)自于一個(gè)實(shí)例池或者是一個(gè)簡(jiǎn)單的JAVA對象target = targetSource.getTarget();if (target != null) {targetClass = target.getClass();}// get the interception chain for this method// 這里獲得定義好的攔截器鏈List chain = this.advised.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(this.advised, proxy, method, targetClass);// Check whether we have any advice. If we don't, we can fallback on direct// reflective invocation of the target, and avoid creating a MethodInvocation.// 如果沒(méi)有設定攔截器,那么我們就直接調用目標的對應方法if (chain.isEmpty()) {// We can skip creating a MethodInvocation: just invoke the target directly// Note that the final invoker must be an InvokerInterceptor so we know it does// nothing but a reflective operation on the target, and no hot swapping or fancy proxyingretVal = AopUtils.invokeJoinpointUsingReflection(target, method, args);}else {// We need to create a method invocation...// invocation = advised.getMethodInvocationFactory().getMethodInvocation(// proxy, method, targetClass, target, args, chain, advised);// 如果有攔截器的設定,那么需要調用攔截器之后才調用目標對象的相應方法// 這里通過(guò)構造一個(gè)ReflectiveMethodInvocation來(lái)實(shí)現,下面我們會(huì )看這個(gè)ReflectiveMethodInvocation類(lèi)invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);// proceed to the joinpoint through the interceptor chain// 這里通過(guò)ReflectiveMethodInvocation來(lái)調用攔截器鏈和相應的目標方法retVal = invocation.proceed();}// massage return value if necessaryif (retVal != null && retVal == target && method.getReturnType().isInstance(proxy)) {// Special case: it returned "this" and the return type of the method is type-compatible// Note that we can't help if the target sets// a reference to itself in another returned object.retVal = proxy;}return retVal;}finally {if (target != null && !targetSource.isStatic()) {// must have come from TargetSourcetargetSource.releaseTarget(target);}if (setProxyContext) {// restore old proxyAopContext.setCurrentProxy(oldProxy);}}}
我們先看看目標對象方法的調用,這里是通過(guò)AopUtils的方法調用 - 使用反射機制來(lái)對目標對象的方法進(jìn)行調用:
public static Object invokeJoinpointUsingReflection(Object target, Method method, Object[] args)throws Throwable {// Use reflection to invoke the method.// 利用放射機制得到相應的方法,并且調用invoketry {if (!Modifier.isPublic(method.getModifiers()) ||!Modifier.isPublic(method.getDeclaringClass().getModifiers())) {method.setAccessible(true);}return method.invoke(target, args);}catch (InvocationTargetException ex) {// Invoked method threw a checked exception.// We must rethrow it. The client won't see the interceptor.throw ex.getTargetException();}catch (IllegalArgumentException ex) {throw new AopInvocationException("AOP configuration seems to be invalid: tried calling method [" +method + "] on target [" + target + "]", ex);}catch (IllegalAccessException ex) {throw new AopInvocationException("Couldn't access method: " + method, ex);}}
對攔截器鏈的調用處理是在ReflectiveMethodInvocation里實(shí)現的:
public Object proceed() throws Throwable {// We start with an index of -1 and increment early.// 這里直接調用目標對象的方法,沒(méi)有攔截器的調用或者攔截器已經(jīng)調用完了,這個(gè)currentInterceptorIndex的初始值是0if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size()) {return invokeJoinpoint();}Object interceptorOrInterceptionAdvice =this.interceptorsAndDynamicMethodMatchers.get(this.currentInterceptorIndex);if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {// Evaluate dynamic method matcher here: static part will already have// been evaluated and found to match.// 這里獲得相應的攔截器,如果攔截器可以匹配的上的話(huà),那就調用攔截器的invoke方法InterceptorAndDynamicMethodMatcher dm =(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {return dm.interceptor.invoke(nextInvocation());}else {// Dynamic matching failed.// Skip this interceptor and invoke the next in the chain.// 如果攔截器匹配不上,那就調用下一個(gè)攔截器,這個(gè)時(shí)候攔截器鏈的位置指示后移并迭代調用當前的proceed方法this.currentInterceptorIndex++;return proceed();}}else {// It's an interceptor, so we just invoke it: The pointcut will have// been evaluated statically before this object was constructed.return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(nextInvocation());}}
這里把當前的攔截器鏈以及在攔截器鏈的位置標志都clone到一個(gè)MethodInvocation對象了,作用是當前的攔截器執行完之后,會(huì )繼續沿著(zhù)得到這個(gè)攔截器鏈執行下面的攔截行為,也就是會(huì )迭代的調用上面這個(gè)proceed:
private ReflectiveMethodInvocation nextInvocation() throws CloneNotSupportedException {ReflectiveMethodInvocation invocation = (ReflectiveMethodInvocation) clone();invocation.currentInterceptorIndex = this.currentInterceptorIndex + 1;invocation.parent = this;return invocation;}
這里的nextInvocation就已經(jīng)包含了當前的攔截鏈的基本信息,我們看到在Interceptor中的實(shí)現比如TransactionInterceptor的實(shí)現中:
public Object invoke(final MethodInvocation invocation) throws Throwable {......//這里是TransactionInterceptor插入的事務(wù)處理代碼,我們會(huì )在后面分析事務(wù)處理實(shí)現的時(shí)候進(jìn)行分析try {//這里是對配置的攔截器鏈進(jìn)行迭代處理的調用retVal = invocation.proceed();}......//省略了和事務(wù)處理的異常處理代碼 ,也是TransactionInterceptor插入的處理else {try {Object result = ((CallbackPreferringPlatformTransactionManager) getTransactionManager()).execute(txAttr,new TransactionCallback() {public Object doInTransaction(TransactionStatus status) {//這里是TransactionInterceptor插入對事務(wù)處理的代碼TransactionInfo txInfo = prepareTransactionInfo(txAttr, joinpointIdentification, status);//這里是對配置的攔截器鏈進(jìn)行迭代處理的調用,接著(zhù)順著(zhù)攔截器進(jìn)行處理try {return invocation.proceed();}......//省略了和事務(wù)處理的異常處理代碼 ,也是TransactionInterceptor插入的處理}
從上面的分析我們看到了Spring AOP的基本實(shí)現,比如Spring怎樣得到Proxy,怎樣利用JAVA Proxy以及反射機制對用戶(hù)定義的攔截器鏈進(jìn)行處理。
聯(lián)系客服