Spring源代码解析(七):SpringAOP中对拦截器调用的实现

前面我们分析了Spring AOP实现中得到Proxy对象的过程,下面我们看看在Spring AOP 中拦截器链是怎样被调用的,也就是Proxy模式是怎样起作用的,或者说Spring是怎样为 我们提供AOP功能的;

在JdkDynamicAopProxy中生成Proxy对象的时候:

Java代码

return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);

这里的this参数对应的是InvocationHandler对象,这里我们的JdkDynamicAopProxy实 现了这个接口,也就是说当Proxy对象的函数被调用的时候,这个InvocationHandler的 invoke方法会被作为回调函数调用,下面我们看看这个方法的实现:

Java代码

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {     MethodInvocation invocation = null;     Object ldProxy = 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 config         return AopUtils.invokeJoinpointUsingReflection (this.advised, method, args);       }       Object retVal = null;       if (this.advised.exposeProxy) {         // make invocation available if necessary         ldProxy = AopContext.setCurrentProxy(proxy);         setProxyContext = true;       }       // May be null. Get as late as possible to minimize the time we "own" the target,       // in case it comes from a pool.       // 这里是得到目标对象的地方,当然这个目标对象可能来自于一个实例 池或者是一个简单的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.       // 如果没有设定拦截器,那么我们就直接调用目标的对应方法       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 proxying         retVal = AopUtils.invokeJoinpointUsingReflection(target, method, args);       }       else {         // We need to create a method invocation...         // invocation = advised.getMethodInvocationFacTory ().getMethodInvocation(         //     proxy, method, targetClass, target, args, chain, advised);         // 如果有拦截器的设定,那么需要调用拦截器之后才调用目标对象 的相应方法         // 这里通过构造一个ReflectiveMethodInvocation来实现,下面我 们会看这个ReflectiveMethodInvocation类         invocation = new ReflectiveMethodInvocation(             proxy, target, method, args, targetClass, chain);         // proceed to the joinpoint through the intercepTor chain         // 这里通过ReflectiveMethodInvocation来调用拦截器链和相应的 目标方法         retVal = invocation.proceed();       }       // massage return value if necessary       if (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 TargetSource         targetSource.releaseTarget(target);       }       if (setProxyContext) {         // resTore old proxy         AopContext.setCurrentProxy(oldProxy);       }     }   }

我们先看看目标对象方法的调用,这里是通过AopUtils的方法调用 – 使用反射机制来 对目标对象的方法进行调用:

Java代码

public static Object invokeJoinpointUsingReflection(Object target, Method method, Object[] args)     throws Throwable {     // Use reflection to invoke the method.     // 利用放射机制得到相应的方法,并且调用invoke     try {       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里实现的:

Java代码

public Object proceed() throws Throwable {     //  We start with an index of -1 and increment early.     // 这里直接调用目标对象的方法,没有拦截器的调用或者拦截器已经调用完 了,这个currentIntercepTorIndex的初始值是0     if (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.       // 这里获得相应的拦截器,如果拦截器可以匹配的上的话,那就调用拦 截器的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.         // 如果拦截器匹配不上,那就调用下一个拦截器,这个时候拦截器 链的位置指示后移并迭代调用当前的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到一个MethodInvocation对 象了,作用是当前的拦截器执行完之后,会继续沿着得到这个拦截器链执行下面的拦截行 为,也就是会迭代的调用上面这个proceed:

Java代码

private ReflectiveMethodInvocation nextInvocation() throws CloneNotSupportedException {     ReflectiveMethodInvocation invocation = (ReflectiveMethodInvocation) clone();     invocation.currentIntercepTorIndex = this.currentIntercepTorIndex + 1;     invocation.parent = this;     return invocation;   }

这里的nextInvocation就已经包含了当前的拦截链的基本信息,我们看到在 IntercepTor中的实现比如TransactionIntercepTor的实现中:

Java代码

public Object invoke(final MethodInvocation invocation) throws Throwable {    ......//这里是TransactionIntercepTor插入的事务处理代码,我们会在后面 分析事务处理实现的时候进行分析       try {         //这里是对配置的拦截器链进行迭代处理的调用         retVal = invocation.proceed();       }    ......//省略了和事务处理的异常处理代码 ,也是TransactionIntercepTor插 入的处理      else {       try {         Object result = ((CallbackPreferringPlatformTransactionManager) getTransactionManager ()).execute(txAttr,             new TransactionCallback() {               public Object doInTransaction(TransactionStatus status) {                 //这里是TransactionIntercepTor插入对事务处 理的代码                 TransactionInfo txInfo = prepareTransactionInfo(txAttr, joinpointIdentification, status);                 //这里是对配置的拦截器链进行迭代处理的调用 ,接着顺着拦截器进行处理                 try {                   return invocation.proceed();                 }    ......//省略了和事务处理的异常处理代码 ,也是TransactionIntercepTor插 入的处理    }

从上面的分析我们看到了Spring AOP的基本实现,比如Spring怎样得到Proxy,怎样利 用JAVA Proxy以及反射机制对用户定义的拦截器链进行处理。

爱的力量大到可以使人忘记一切,却又小到连一粒嫉妒的沙石也不能容纳

Spring源代码解析(七):SpringAOP中对拦截器调用的实现

相关文章:

你感兴趣的文章:

标签云: