Sping源码解析之AOP拦截器链

我们继续上一节的讨论来看看在Spring的AOP中,拦截器链是如何调用的。
一:首先我们来看一下JdkDynamicAopProxy是如何生成代理对象的.JdkDynamicAopProxy实现了InvocationHandler,invoke方法的源码如下:
/**
  * Implementation of <code>InvocationHandler.invoke</code>.
  * <p>Callers will see exactly the exception thrown by the target,
  * unless a hook method throws an exception.
  */
 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)) {
    // The target does not implement the equals(Object) method itself.
    return equals(args[0]);
   }
   if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
    // The target does not implement the hashCode() method itself.
    return hashCode();
   }
   if (!this.advised.opaque && method.getDeclaringClass().isInterface() &&
     method.getDeclaringClass().isAssignableFrom(Advised.class)) {
    // Service invocations on ProxyConfig with the proxy config...
    return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
   }

   Object retVal;

   if (this.advised.exposeProxy) {
    // Make invocation available if necessary.
    oldProxy = 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.
   target = targetSource.getTarget();
   if (target != null) {
    targetClass = target.getClass();
   }

   // Get the interception chain for this method.
   List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(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 = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);
    // Proceed to the joinpoint through the interceptor chain.
    retVal = invocation.proceed();
   }

   // Massage return value if necessary.
   if (retVal != null && retVal == target && method.getReturnType().isInstance(proxy) &&
     !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) {
    // 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);
   }
  }
 }
从这个方法的源码中,我们看出如果没有配置拦截器链,会直接利用反射调用的目标对象的method,详见代码AopUtils.invokeJoinpointUsingReflection(target, method, args)。如果配置了拦截器链,则把处理逻辑转交给ReflectiveMethodInvocation的process方法。Cglib2AopProxy的intercept拦截的方式跟JdkDynamicAopProxy是相似的,这里不多做介绍,我们继续来看看ReflectiveMethodInvocation的process的源码。
public Object proceed() throws Throwable {
  // We start with an index of -1 and increment early.
  if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
   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.
   InterceptorAndDynamicMethodMatcher dm =
       (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
   if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {
    return dm.interceptor.invoke(this);
   }
   else {
    // Dynamic matching failed.
    // Skip this interceptor and invoke the next in the chain.
    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(this);
  }
 }
看到这个变种责任链模式的应用是不是很熟悉哈,其实这个跟长软的基础框架中拦截器的实现原理是一致的。非常巧妙的一种处理方式,自己慢慢去领会吧。

二:我们再来看看拦截器链的配置和获取,从JdkDynamicAopProxy的invoke方法的源码List chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);我们可以逆向追踪chain的来源。
我们进入到AdvisedSupport类中来看看getInterceptorsAndDynamicInterceptionAdvice的源码
/**
  * Determine a list of {@link org.aopalliance.intercept.MethodInterceptor} objects
  * for the given method, based on this configuration.
  * @param method the proxied method
  * @param targetClass the target class
  * @return List of MethodInterceptors (may also include InterceptorAndDynamicMethodMatchers)
  */
 public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, Class targetClass) {
  MethodCacheKey cacheKey = new MethodCacheKey(method);
  List<Object> cached = this.methodCache.get(cacheKey);
  if (cached == null) {
   cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(
     this, method, targetClass);
   this.methodCache.put(cacheKey, cached);
  }
  return cached;
 }
这里很明显使用了缓存技术,读取一次便存储在methodCache中,第一次读取的操作是DefaultAdvisorChainFactory的getInterceptorsAndDynamicInterceptionAdvice方法中完成的。
public class DefaultAdvisorChainFactory implements AdvisorChainFactory, Serializable {

 public List<Object> getInterceptorsAndDynamicInterceptionAdvice(
   Advised config, Method method, Class targetClass) {

  // This is somewhat tricky... we have to process introductions first,
  // but we need to preserve order in the ultimate list.
  List<Object> interceptorList = new ArrayList<Object>(config.getAdvisors().length);
  boolean hasIntroductions = hasMatchingIntroductions(config, targetClass);
  AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();
  for (Advisor advisor : config.getAdvisors()) {
   if (advisor instanceof PointcutAdvisor) {
    // Add it conditionally.
    PointcutAdvisor pointcutAdvisor = (PointcutAdvisor) advisor;
    if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(targetClass)) {
     MethodInterceptor[] interceptors = registry.getInterceptors(advisor);
     MethodMatcher mm = pointcutAdvisor.getPointcut().getMethodMatcher();
     if (MethodMatchers.matches(mm, method, targetClass, hasIntroductions)) {
      if (mm.isRuntime()) {
       // Creating a new object instance in the getInterceptors() method
       // isn't a problem as we normally cache created chains.
       for (MethodInterceptor interceptor : interceptors) {
        interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptor, mm));
       }
      }
      else {
       interceptorList.addAll(Arrays.asList(interceptors));
      }
     }
    }
   }
   else if (advisor instanceof IntroductionAdvisor) {
    IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
    if (config.isPreFiltered() || ia.getClassFilter().matches(targetClass)) {
     Interceptor[] interceptors = registry.getInterceptors(advisor);
     interceptorList.addAll(Arrays.asList(interceptors));
    }
   }
   else {
    Interceptor[] interceptors = registry.getInterceptors(advisor);
    interceptorList.addAll(Arrays.asList(interceptors));
   }
  }
  return interceptorList;
 }

 /**
  * Determine whether the Advisors contain matching introductions.
  */
 private static boolean hasMatchingIntroductions(Advised config, Class targetClass) {
  for (int i = 0; i < config.getAdvisors().length; i++) {
   Advisor advisor = config.getAdvisors()[i];
   if (advisor instanceof IntroductionAdvisor) {
    IntroductionAdvisor ia = (IntroductionAdvisor) advisor;
    if (ia.getClassFilter().matches(targetClass)) {
     return true;
    }
   }
  }
  return false;
 }

}
在getInterceptorsAndDynamicInterceptionAdvice中,最核心的操作是registry.getInterceptors(advisor).这个registery是通过AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance();来获取的。我们再来看一下GlobalAdvisorAdapterRegistry的源码:
public abstract class GlobalAdvisorAdapterRegistry {

 /**
  * Keep track of a single instance so we can return it to classes that request it.
  */
 private static final AdvisorAdapterRegistry instance = new DefaultAdvisorAdapterRegistry();
 
 /**
  * Return the singleton DefaultAdvisorAdapterRegistry instance.
  */
 public static AdvisorAdapterRegistry getInstance() {
  return instance;
 }

}
很显然这是一个单例模式,真正得到的registery是DefaultAdvisorAdapterRegistry类型的.DefaultAdvisorAdapterRegistry的源码解析如下:
public class DefaultAdvisorAdapterRegistry implements AdvisorAdapterRegistry, Serializable {

 private final List<AdvisorAdapter> adapters = new ArrayList<AdvisorAdapter>(3);


 /**
  * Create a new DefaultAdvisorAdapterRegistry, registering well-known adapters.
  */
 public DefaultAdvisorAdapterRegistry() {
  registerAdvisorAdapter(new MethodBeforeAdviceAdapter());
  registerAdvisorAdapter(new AfterReturningAdviceAdapter());
  registerAdvisorAdapter(new ThrowsAdviceAdapter());
 }


 public Advisor wrap(Object adviceObject) throws UnknownAdviceTypeException {
  if (adviceObject instanceof Advisor) {
   return (Advisor) adviceObject;
  }
  if (!(adviceObject instanceof Advice)) {
   throw new UnknownAdviceTypeException(adviceObject);
  }
  Advice advice = (Advice) adviceObject;
  if (advice instanceof MethodInterceptor) {
   // So well-known it doesn't even need an adapter.
   return new DefaultPointcutAdvisor(advice);
  }
  for (AdvisorAdapter adapter : this.adapters) {
   // Check that it is supported.
   if (adapter.supportsAdvice(advice)) {
    return new DefaultPointcutAdvisor(advice);
   }
  }
  throw new UnknownAdviceTypeException(advice);
 }

 public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException {
  List<MethodInterceptor> interceptors = new ArrayList<MethodInterceptor>(3);
  Advice advice = advisor.getAdvice();
  if (advice instanceof MethodInterceptor) {
   interceptors.add((MethodInterceptor) advice);
  }
  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[interceptors.size()]);
 }

 public void registerAdvisorAdapter(AdvisorAdapter adapter) {
  this.adapters.add(adapter);
 }

}
在DefaultAdvisorAdapterRegistry的初始化方法中,我们可以看到注册了三个适配器,从MethodBeforeAdviceAdapter、AfterReturningAdviceAdapter以及ThrowsAdviceAdapter的名字就可以看出来他们对应的Advice类型。
以MethodBeforeAdviceAdapter为例,我们来看看源码:
class MethodBeforeAdviceAdapter implements AdvisorAdapter, Serializable {

 public boolean supportsAdvice(Advice advice) {
  return (advice instanceof MethodBeforeAdvice);
 }

 public MethodInterceptor getInterceptor(Advisor advisor) {
  MethodBeforeAdvice advice = (MethodBeforeAdvice) advisor.getAdvice();
  return new MethodBeforeAdviceInterceptor(advice);
 }

}
接下来我们来看一下MethodBeforeAdviceInterceptor的源码实现:
public class MethodBeforeAdviceInterceptor implements MethodInterceptor, Serializable {

 private MethodBeforeAdvice advice;


 /**
  * Create a new MethodBeforeAdviceInterceptor for the given advice.
  * @param advice the MethodBeforeAdvice to wrap
  */
 public MethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) {
  Assert.notNull(advice, "Advice must not be null");
  this.advice = advice;
 }

 public Object invoke(MethodInvocation mi) throws Throwable {
  this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis() );
  return mi.proceed();
 }

}
这里重点关注一下mi.proceed()方法.
AfterReturningAdviceInterceptor和ThrowAdviceInterceptor的实现类似于MethodBeforeAdviceInterceptor,这里不多介绍。
至此,我们再来回顾一下ReflectiveMethodInvocation的process方法,
public Object proceed() throws Throwable {
  // We start with an index of -1 and increment early.
  if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
   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.
   InterceptorAndDynamicMethodMatcher dm =
       (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
   if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {
    return dm.interceptor.invoke(this);
   }
   else {
    // Dynamic matching failed.
    // Skip this interceptor and invoke the next in the chain.
    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(this);
  }
 }
我们来关注一下interceptor.invoke(this),其实在这个interceptor的invoke方法里又返过来调用这个process方法。
正是这两个地方的交互,形成一个巧妙和责任链处理模式。这里需要用心去体会一下。

猜你喜欢

转载自hai19850514.iteye.com/blog/1830238