/** * Implementation of {@code InvocationHandler.invoke}. * <p>Callers will see exactly the exception thrown by the target, * unless a hook method throws an exception. * InvocationHandler 的 INVOK方法 AOP调用的入口方法 */ @Override @Nullable public Object invoke(Object proxy, Method method, Object[] args)throws Throwable { ObjectoldProxy=null; booleansetProxyContext=false;
try { //被代理对象的equals方法和hashCode方法是不能被代理的,不会走切面 if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) { // The target does not implement the equals(Object) method itself. // 目标不实现equals(Object)方法本身。 return equals(args[0]); } 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()声明 - > dispatch到代理配置。 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... // ProxyConfig上的服务调用与代理配置... 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. // 2.拿到我们被代理的对象实例 //这个target就是被代理实例 target = targetSource.getTarget(); Class<?> targetClass = (target != null ? target.getClass() : null);
// Get the interception chain for this method. // 3.获取拦截器链:例如使用@Around注解时会找到AspectJAroundAdvice,还有ExposeInvocationInterceptor //从代理工厂中拿过滤器链 Object是一个MethodInterceptor类型的对象,其实就是一个advice对象 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. // 4.检查我们是否有任何拦截器(advice)。 如果没有,直接反射调用目标,并避免创建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); // 5.不存在拦截器链,则直接进行反射调用 retVal = AopUtils.invokeJoinpointUsingReflection(target, method, argsToUse); } else { // 6.如果存在拦截器,则创建一个ReflectiveMethodInvocation:代理对象、被代理对象、方法、参数、 // 被代理对象的Class、拦截器链作为参数创建ReflectiveMethodInvocation // We need to create a method invocation... MethodInvocationinvocation= newReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain); // Proceed to the joinpoint through the interceptor chain. // 7.触发ReflectiveMethodInvocation的执行方法 retVal = invocation.proceed(); }
// Massage return value if necessary. // 8.必要时转换返回值 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. // 1.如果所有拦截器都执行完毕(index是从-1开始,所以跟size - 1比较),则直接使用反射调用连接点(也就是我们原本的方法) //如果执行链中的advice全部执行完,则直接调用joinPoint方法,就是被代理方法 if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) { return invokeJoinpoint(); }
// 2.每次调用时,将索引的值递增,并通过索引拿到要执行的拦截器 ObjectinterceptorOrInterceptionAdvice= this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex); // 3.判断拦截器是否为InterceptorAndDynamicMethodMatcher类型(动态方法匹配拦截器) 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)) { 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. // 4.只是一个普通的拦截器,则触发拦截器链责任链的调用,并且参数为ReflectiveMethodInvocation本身 //调用MethodInterceptor中的invoke方法 return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this); } }
/** * Invoke the given target via reflection, as part of an AOP method invocation. * 使用反射调用切点 * */ @Nullable publicstatic Object invokeJoinpointUsingReflection(@Nullable Object target, Method method, Object[] args) throws Throwable {
// Use reflection to invoke the method. try { // 使用反射调用方法 ReflectionUtils.makeAccessible(method); return method.invoke(target, args); } catch (InvocationTargetException ex) { // Invoked method threw a checked exception. // We must rethrow it. The client won't see the interceptor. throw ex.getTargetException(); } catch (IllegalArgumentException ex) { thrownewAopInvocationException("AOP configuration seems to be invalid: tried calling method [" + method + "] on target [" + target + "]", ex); } catch (IllegalAccessException ex) { thrownewAopInvocationException("Could not access method [" + method + "]", ex); } }
/** * Create a new MethodBeforeAdviceInterceptor for the given advice. * @param advice the MethodBeforeAdvice to wrap */ publicMethodBeforeAdviceInterceptor(MethodBeforeAdvice advice) { Assert.notNull(advice, "Advice must not be null"); this.advice = advice; }