Delegate interface for a configured AOP proxy, allowing for the creation of actual proxy objects. Out-of-the-box implementations are available for JDK dynamic proxies and for CGLIB proxies, as applied by DefaultAopProxyFactory.
if (this.advised.exposeProxy) { // Make invocation available if necessary. oldProxy = AopContext.setCurrentProxy(proxy); setProxyContext = true; }
// Get as late as possible to minimize the time we "own" the target, // in case it comes from a pool. target = targetSource.getTarget(); Class<?> targetClass = (target != null ? target.getClass() : null);
// 判断是否有需要执行的通知(advice),即上面获得的拦截器链,如果为空,就直接执行目标对象的方法 // 不需要走增强逻辑了 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. // 在一些特殊情况下转换一下请求参数,不清楚什么情况下会使用,知道的读者可以告诉我 Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args); // 通过反射的方式调用目标对象的对应方法 retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse); } else { // 需要执行拦截器链的情况下,创建一个ReflectiveMethodInvocation并执行,后面细讲 invocation = newReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain); retVal = invocation.proceed(); }
// 给返回值做一下马杀鸡(原文就是这么说的-_-||),即处理一下返回值 Class<?> returnType = method.getReturnType(); if (retVal != null && retVal == target && returnType != Object.class && returnType.isInstance(proxy) && !RawTargetAccess.class.isAssignableFrom(method.getDeclaringClass())) { // 一些特殊情况下,原方法会返回this,即目标对象,那么这里应该返回代理对象,而不是原对象,所以返回值修改为当前代理对象 retVal = proxy; } elseif (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) { thrownewAopInvocationException( "Null return value from advice does not match primitive return type for: " + method); } return retVal; } finally { if (target != null && !targetSource.isStatic()) { // Must have come from TargetSource. targetSource.releaseTarget(target); } if (setProxyContext) { // Restore old proxy. AopContext.setCurrentProxy(oldProxy); } } }
// This is somewhat tricky... We have to process introductions first, // but we need to preserve order in the ultimate list. // GlobalAdvisorAdapterRegistry.getInstance() 方法返回的是一个单例 // 即DefaultAdvisorAdapterRegistry实例 AdvisorAdapterRegistryregistry= GlobalAdvisorAdapterRegistry.getInstance(); Advisor[] advisors = config.getAdvisors(); List<Object> interceptorList = newArrayList<>(advisors.length); Class<?> actualClass = (targetClass != null ? targetClass : method.getDeclaringClass()); BooleanhasIntroductions=null;
// 遍历所有的通知 for (Advisor advisor : advisors) { if (advisor instanceof PointcutAdvisor) { // 这里不细讲了,简单来说就是需要判断该方法是否被当前通知处理 PointcutAdvisorpointcutAdvisor= (PointcutAdvisor) advisor; if (config.isPreFiltered() || pointcutAdvisor.getPointcut().getClassFilter().matches(actualClass)) { MethodMatchermm= pointcutAdvisor.getPointcut().getMethodMatcher(); boolean match; if (mm instanceof IntroductionAwareMethodMatcher) { if (hasIntroductions == null) { hasIntroductions = hasMatchingIntroductions(advisors, actualClass); } match = ((IntroductionAwareMethodMatcher) mm).matches(method, actualClass, hasIntroductions); } else { match = mm.matches(method, actualClass); } if (match) { // 如果匹配上了,调用DefaultAdvisorAdapterRegistry#getInterceptors进行包装 // 后面会细讲这个方法 MethodInterceptor[] interceptors = registry.getInterceptors(advisor); 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(newInterceptorAndDynamicMethodMatcher(interceptor, mm)); } } else { interceptorList.addAll(Arrays.asList(interceptors)); } } } } elseif (advisor instanceof IntroductionAdvisor) { IntroductionAdvisoria= (IntroductionAdvisor) advisor; if (config.isPreFiltered() || ia.getClassFilter().matches(actualClass)) { Interceptor[] interceptors = registry.getInterceptors(advisor); interceptorList.addAll(Arrays.asList(interceptors)); } } else { Interceptor[] interceptors = registry.getInterceptors(advisor); interceptorList.addAll(Arrays.asList(interceptors)); } }
public Object getProxy(@Nullable ClassLoader classLoader) { if (logger.isTraceEnabled()) { logger.trace("Creating CGLIB proxy: " + this.advised.getTargetSource()); }
try { Class<?> rootClass = this.advised.getTargetClass(); Assert.state(rootClass != null, "Target class must be available for creating a CGLIB proxy");
Callback[] callbacks = getCallbacks(rootClass); Class<?>[] types = newClass<?>[callbacks.length]; for (intx=0; x < types.length; x++) { types[x] = callbacks[x].getClass(); } // fixedInterceptorMap only populated at this point, after getCallbacks call above enhancer.setCallbackFilter(newProxyCallbackFilter( this.advised.getConfigurationOnlyCopy(), this.fixedInterceptorMap, this.fixedInterceptorOffset)); enhancer.setCallbackTypes(types);
// Generate the proxy class and create a proxy instance. return createProxyClassAndInstance(enhancer, callbacks); } catch (CodeGenerationException | IllegalArgumentException ex) { thrownewAopConfigException("Could not generate CGLIB subclass of " + this.advised.getTargetClass() + ": Common causes of this problem include using a final class or a non-visible class", ex); } catch (Throwable ex) { // TargetSource.getTarget() failed thrownewAopConfigException("Unexpected AOP exception", ex); } }
public Object intercept(Object proxy, Method method, Object[] args, MethodProxy methodProxy)throws Throwable { ObjectoldProxy=null; booleansetProxyContext=false; Objecttarget=null; TargetSourcetargetSource=this.advised.getTargetSource(); try { if (this.advised.exposeProxy) { // Make invocation available if necessary. oldProxy = AopContext.setCurrentProxy(proxy); setProxyContext = true; } // Get as late as possible to minimize the time we "own" the target, in case it comes from a pool... target = targetSource.getTarget(); Class<?> targetClass = (target != null ? target.getClass() : null); List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); Object retVal; // Check whether we only have one InvokerInterceptor: that is, // no real advice, but just reflective invocation of the target. if (chain.isEmpty() && Modifier.isPublic(method.getModifiers())) { // 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. Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args); retVal = methodProxy.invoke(target, argsToUse); } else { // We need to create a method invocation... retVal = newCglibMethodInvocation(proxy, target, method, args, targetClass, chain, methodProxy).proceed(); } retVal = processReturnType(proxy, target, method, retVal); return retVal; } finally { if (target != null && !targetSource.isStatic()) { targetSource.releaseTarget(target); } if (setProxyContext) { // Restore old proxy. AopContext.setCurrentProxy(oldProxy); } } }
publicintaccept(Method method) { if (AopUtils.isFinalizeMethod(method)) { logger.trace("Found finalize() method - using NO_OVERRIDE"); return NO_OVERRIDE; } if (!this.advised.isOpaque() && method.getDeclaringClass().isInterface() && method.getDeclaringClass().isAssignableFrom(Advised.class)) { if (logger.isTraceEnabled()) { logger.trace("Method is declared on Advised interface: " + method); } return DISPATCH_ADVISED; } // We must always proxy equals, to direct calls to this. if (AopUtils.isEqualsMethod(method)) { if (logger.isTraceEnabled()) { logger.trace("Found 'equals' method: " + method); } return INVOKE_EQUALS; } // We must always calculate hashCode based on the proxy. if (AopUtils.isHashCodeMethod(method)) { if (logger.isTraceEnabled()) { logger.trace("Found 'hashCode' method: " + method); } return INVOKE_HASHCODE; } Class<?> targetClass = this.advised.getTargetClass(); // Proxy is not yet available, but that shouldn't matter. List<?> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass); booleanhaveAdvice= !chain.isEmpty(); booleanexposeProxy=this.advised.isExposeProxy(); booleanisStatic=this.advised.getTargetSource().isStatic(); booleanisFrozen=this.advised.isFrozen(); if (haveAdvice || !isFrozen) { // If exposing the proxy, then AOP_PROXY must be used. if (exposeProxy) { if (logger.isTraceEnabled()) { logger.trace("Must expose proxy on advised method: " + method); } return AOP_PROXY; } Stringkey= method.toString(); // Check to see if we have fixed interceptor to serve this method. // Else use the AOP_PROXY. if (isStatic && isFrozen && this.fixedInterceptorMap.containsKey(key)) { if (logger.isTraceEnabled()) { logger.trace("Method has advice and optimizations are enabled: " + method); } // We know that we are optimizing so we can use the FixedStaticChainInterceptors. intindex=this.fixedInterceptorMap.get(key); return (index + this.fixedInterceptorOffset); } else { if (logger.isTraceEnabled()) { logger.trace("Unable to apply any optimizations to advised method: " + method); } return AOP_PROXY; } } else { // See if the return type of the method is outside the class hierarchy of the target type. // If so we know it never needs to have return type massage and can use a dispatcher. // If the proxy is being exposed, then must use the interceptor the correct one is already // configured. If the target is not static, then we cannot use a dispatcher because the // target needs to be explicitly released after the invocation. if (exposeProxy || !isStatic) { return INVOKE_TARGET; } Class<?> returnType = method.getReturnType(); if (targetClass != null && returnType.isAssignableFrom(targetClass)) { if (logger.isTraceEnabled()) { logger.trace("Method return type is assignable from target type and " + "may therefore return 'this' - using INVOKE_TARGET: " + method); } return INVOKE_TARGET; } else { if (logger.isTraceEnabled()) { logger.trace("Method return type ensures 'this' cannot be returned - " + "using DISPATCH_TARGET: " + method); } return DISPATCH_TARGET; } } }