Spring源码分析-AOP拦截器链的使用(六)

来源:互联网 发布:淘宝win10激活码危险 编辑:程序博客网 时间:2024/05/16 14:49

我们继续上一节的讨论来看看在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);}}}

从这个方法的源码中,我们看出如果没有配置拦截器链,会直接利用反射调用的目标对象的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 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方法

正是这两个地方的交互,形成一个巧妙和责任链处理模式。这里需要用心去体会一下。





原创粉丝点击