我们继续上一节的讨论来看看在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 = null; 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]) ? Boolean.TRUE : Boolean.FALSE); } if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) { // The target does not implement the hashCode() method itself. return new Integer(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 = null; if (this.advised.exposeProxy) { // Make invocation available if necessary. oldProxy = 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. target = targetSource.getTarget(); if (target != null) { targetClass = target.getClass(); } // Get the interception chain for this method. List 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); } } }
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 getInterceptorsAndDynamicInterceptionAdvice(Method method, Class targetClass) { MethodCacheKey cacheKey = new MethodCacheKey(method); List cached = (List) 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 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 interceptorList = new ArrayList(config.getAdvisors().length); boolean hasIntroductions = hasMatchingIntroductions(config, targetClass); AdvisorAdapterRegistry registry = GlobalAdvisorAdapterRegistry.getInstance(); Advisor[] advisors = config.getAdvisors(); for (int i = 0; i < advisors.length; i++) { Advisor advisor = advisors[i]; 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 (int j = 0; j < interceptors.length; j++) { interceptorList.add(new InterceptorAndDynamicMethodMatcher(interceptors[j], 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 adapters = new ArrayList(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 (int i = 0; i < this.adapters.size(); i++) { // Check that it is supported. AdvisorAdapter adapter = (AdvisorAdapter) this.adapters.get(i); if (adapter.supportsAdvice(advice)) { return new DefaultPointcutAdvisor(advice); } } throw new UnknownAdviceTypeException(advice); } public MethodInterceptor[] getInterceptors(Advisor advisor) throws UnknownAdviceTypeException { List interceptors = new ArrayList(3); Advice advice = advisor.getAdvice(); if (advice instanceof MethodInterceptor) { interceptors.add(advice); } for (int i = 0; i < this.adapters.size(); i++) { AdvisorAdapter adapter = (AdvisorAdapter) this.adapters.get(i); if (adapter.supportsAdvice(advice)) { interceptors.add(adapter.getInterceptor(advisor)); } } if (interceptors.isEmpty()) { throw new UnknownAdviceTypeException(advisor.getAdvice()); } return (MethodInterceptor[]) 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); } }
接下来我们来看一下MethodBeforeAdvice的源码实现:
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方法。
正是这两个地方的交互,形成一个巧妙和责任链处理模式。这里需要用心去体会一下。