@Override public AopProxy createAopProxy(AdvisedSupport config)throws AopConfigException { //判断是使用JDK的动态代理还是CGLIB代理 //optimize:用来控制通过CGLIB创建的代理是否使用激进的优化策略。仅用于CGLIB; //proxyTargetClass:这个属性为 true 时,目标类本身本代理而不是目标类的接口, //如果这个属性值被设为 true,CGLIB 代理将被创建, //设置方式:<aop:aspectj-autoproxy proxy-target-class="true"/>; //hasNoUserSuppliedProxyInterfaces:是否存在代理接口; if (config.isOptimize() || config.isProxyTargetClass() || hasNoUserSuppliedProxyInterfaces(config)) { Class<?> targetClass = config.getTargetClass(); if (targetClass == null) { thrownewAopConfigException("TargetSource cannot determine target class: " + "Either an interface or a target is required for proxy creation."); } //如果目标类实现了接口,返回true //isProxyClass:当且仅当使用getProxyClass方法或newProxyInstance方法将指定的类动态生成为代理类时,返回true。 if (targetClass.isInterface() || Proxy.isProxyClass(targetClass)) { //使用JDK动态代理 returnnewJdkDynamicAopProxy(config); } //使用CGLIB代理,ObjenesisCglibAopProxy 继承 CglibAopProxy returnnewObjenesisCglibAopProxy(config); } //上面的条件不满足则使用JDK动态代理 else { returnnewJdkDynamicAopProxy(config); } }
这里有三个条件判断,详见代码注释。 贴一张AopProxy的继承关系图:
JDK动态代理JdkDynamicAopProxy
1 2 3 4 5 6 7 8 9 10 11 12 13
/** * Construct a new JdkDynamicAopProxy for the given AOP configuration. * @param config the AOP configuration as AdvisedSupport object * @throws AopConfigException if the config is invalid. We try to throw an informative * exception in this case, rather than let a mysterious failure happen later. */ publicJdkDynamicAopProxy(AdvisedSupport config)throws AopConfigException { Assert.notNull(config, "AdvisedSupport must not be null"); if (config.getAdvisors().length == 0 && config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE) { thrownewAopConfigException("No advisors and no TargetSource specified"); } this.advised = config; }
/** * Create a new ObjenesisCglibAopProxy for the given AOP configuration. * @param config the AOP configuration as AdvisedSupport object */ publicObjenesisCglibAopProxy(AdvisedSupport config) { super(config); } /** * Create a new CglibAopProxy for the given AOP configuration. * @param config the AOP configuration as AdvisedSupport object * @throws AopConfigException if the config is invalid. We try to throw an informative * exception in this case, rather than let a mysterious failure happen later. */ publicCglibAopProxy(AdvisedSupport config)throws AopConfigException { Assert.notNull(config, "AdvisedSupport must not be null"); if (config.getAdvisors().length == 0 && config.getTargetSource() == AdvisedSupport.EMPTY_TARGET_SOURCE) { thrownewAopConfigException("No advisors and no TargetSource specified"); } this.advised = config; this.advisedDispatcher = newAdvisedDispatcher(this.advised); }
try { //equals方法处理 if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) { // The target does not implement the equals(Object) method itself. return equals(args[0]); } //hashCode方法处理 elseif (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) { // The target does not implement the hashCode() method itself. return hashCode(); } elseif (method.getDeclaringClass() == DecoratingProxy.class) { // There is only getDecoratedClass() declared -> dispatch to proxy config. // 只有getDecoratedClass()声明->分派到代理配置。 return AopProxyUtils.ultimateTargetClass(this.advised); } elseif (!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; }
// 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);
// 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. Object[] argsToUse = AopProxyUtils.adaptArgumentsIfNecessary(method, args); // 如果没有发现任何拦截器那么直接调入切点方法 retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse); } else { // We need to create a method invocation... // 将拦截器封装在 ReflectiveMethodInvocation // 以便于使用期 proceed 进行链接表用拦截器 MethodInvocationinvocation= newReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain); // Proceed to the joinpoint through the interceptor chain. // 执行拦截器链 retVal = invocation.proceed(); }
// 返回结果 // Massage return value if necessary. Class<?> returnType = method.getReturnType(); if (retVal != null && retVal == target && returnType != Object.class && returnType.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; } 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); } } }
@Override @Nullable public Object proceed()throws Throwable { // We start with an index of -1 and increment early. // 执行完所有增强后执行切点方法 if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) { return invokeJoinpoint(); }
// 获取下一个要执行的拦截器 ObjectinterceptorOrInterceptionAdvice= 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. InterceptorAndDynamicMethodMatcherdm= (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice; Class<?> targetClass = (this.targetClass != null ? this.targetClass : this.method.getDeclaringClass()); //匹配 if (dm.methodMatcher.matches(this.method, targetClass, this.arguments)) { // 在这一步会调用增强器,逻辑在内部实现,比如MethodBeforeAdviceInterceptor 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); } }
@Override publicvoidbefore(Method method, Object[] args, @Nullable Object target)throws Throwable { //首先,获取JoinPointMatch,在被分派到的连接点上获取当前连接点匹配。 //之后调用advice方法。 invokeAdviceMethod(getJoinPointMatch(), null, null); } /** * Invoke the advice method. * @param jpMatch the JoinPointMatch that matched this execution join point * @param returnValue the return value from the method execution (may be null) * @param ex the exception thrown by the method execution (may be null) * @return the invocation result * @throws Throwable in case of invocation failure */ protected Object invokeAdviceMethod( @Nullable JoinPointMatch jpMatch, @Nullable Object returnValue, @Nullable Throwable ex) throws Throwable {
@Override 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. // 生成代理类以及创建代理,由子类ObjenesisCglibAopProxy实现 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); } }
// Choose an "aop" interceptor (used for AOP calls). CallbackaopInterceptor=newDynamicAdvisedInterceptor(this.advised);
// Choose a "straight to target" interceptor. (used for calls that are // unadvised but can return this). May be required to expose the proxy. Callback targetInterceptor; if (exposeProxy) { targetInterceptor = (isStatic ? newStaticUnadvisedExposedInterceptor(this.advised.getTargetSource().getTarget()) : newDynamicUnadvisedExposedInterceptor(this.advised.getTargetSource())); } else { targetInterceptor = (isStatic ? newStaticUnadvisedInterceptor(this.advised.getTargetSource().getTarget()) : newDynamicUnadvisedInterceptor(this.advised.getTargetSource())); }
// Choose a "direct to target" dispatcher (used for // unadvised calls to static targets that cannot return this). CallbacktargetDispatcher= (isStatic ? newStaticDispatcher(this.advised.getTargetSource().getTarget()) : newSerializableNoOp());
Callback[] mainCallbacks = newCallback[] { aopInterceptor, // for normal advice targetInterceptor, // invoke target without considering advice, if optimized newSerializableNoOp(), // no override for methods mapped to this targetDispatcher, this.advisedDispatcher, newEqualsInterceptor(this.advised), newHashCodeInterceptor(this.advised) };
Callback[] callbacks;
// If the target is a static one and the advice chain is frozen, // then we can make some optimizations by sending the AOP calls // direct to the target using the fixed chain for that method. if (isStatic && isFrozen) { Method[] methods = rootClass.getMethods(); Callback[] fixedCallbacks = newCallback[methods.length]; this.fixedInterceptorMap = newHashMap<>(methods.length);
// TODO: small memory optimization here (can skip creation for methods with no advice) for (intx=0; x < methods.length; x++) { List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(methods[x], rootClass); fixedCallbacks[x] = newFixedChainStaticTargetInterceptor( chain, this.advised.getTargetSource().getTarget(), this.advised.getTargetClass()); this.fixedInterceptorMap.put(methods[x].toString(), x); }
// Now copy both the callbacks from mainCallbacks // and fixedCallbacks into the callbacks array. callbacks = newCallback[mainCallbacks.length + fixedCallbacks.length]; System.arraycopy(mainCallbacks, 0, callbacks, 0, mainCallbacks.length); System.arraycopy(fixedCallbacks, 0, callbacks, mainCallbacks.length, fixedCallbacks.length); this.fixedInterceptorOffset = mainCallbacks.length; } else { callbacks = mainCallbacks; } return callbacks; }