JdkDynamicAopProxy 实现了 InvocationHandler 接口,所以在创建代理对象的时候传递了 this
// jdk动态代理创建代理对象
return Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);
进入方法调用
@Override
@Nullable
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
System.out.println("jdk aop 拦截方法:" + method.getName());
Object oldProxy = null;
boolean setProxyContext = false;
// 代理目标
TargetSource targetSource = this.advised.targetSource;
// 代理目标对象
Object target = null;
try {
if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
// 如何代理接口没有定义equals方法,则调用JdkDynamicAopProxy的重写的equals方法
// The target does not implement the equals(Object) method itself.
return equals(args[0]);
} else if (!this.hashCodeDefined && AopUtils.isHashCodeMethod(method)) {
// 同上
// The target does not implement the hashCode() method itself.
return hashCode();
} else if (method.getDeclaringClass() == DecoratingProxy.class) {
// There is only getDecoratedClass() declared -> dispatch to proxy config.
return AopProxyUtils.ultimateTargetClass(this.advised);
} else if (!this.advised.opaque
&& method.getDeclaringClass().isInterface()
&& method.getDeclaringClass().isAssignableFrom(Advised.class)) {
// Service invocations on ProxyConfig with the proxy config...
/*
opaque:表示代理对象是否可以转换成 Advised 类型,默认为false;
被代理类是否接口;
被代理类是否实现了接口Advised; 通常情况下被代理的对象或者接口都不会
*/
return AopUtils.invokeJoinpointUsingReflection(this.advised, method, args);
}
// 返回结果
Object retVal;
// 如果暴露代理的话,放到 currentProxy(ThreadLocal)中
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对象
Class<?> targetClass = (target != null ? target.getClass() : null);
// Get the interception chain for this method.
// 获取方法拦截的调用链
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.
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 {
// 创建MethodInvocation,对方法进行拦截调用
MethodInvocation 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.
// 整理返回值
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;
} else if (retVal == null && returnType != Void.TYPE && returnType.isPrimitive()) {
throw new AopInvocationException("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);
}
}
}
过程:
- 首先判断方法是否为 equals 或者 hashcode,如果被代理对象没有实现的话,使用代理对象重写的方法;
- 判断如果父类是 DecoratingProxy ,直接调用目标对象;
- 判断被代理类是否为接口,是否为Advised或者父接口,是否可以转换成Advised类型,满足的话,直接调用目标方法;
- 如果要暴露代理对象的话,将代理配置放到 ThreadLocal 中,实现该线程下共享;
- 获取代理对象,获取方法拦截的调用链;
- 如果调用链为空,那么直接调用目标方法;
- 调用链不为空,创建 MethodInvocation 对象,执行方法的拦截器;(这里用到责任链模式)
- 整理最终返回值,返回。
执行方法拦截在 ReflectiveMethodInvocation 对象中执行,首先看下该类父类关系:
入口方法 proceed() 由接口 Joinpoint 提供.
package org.aopalliance.intercept;
import java.lang.reflect.AccessibleObject;
public interface Joinpoint {
// 继续进行链中的下一个拦截器。
Object proceed() throws Throwable;
// 被代理对象
Object getThis();
AccessibleObject getStaticPart();
}
@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();
}
// 根据顺序获取目标方法的拦截方法
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;
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.
// 普通的拦截器:
/*
ExposeInvocationInterceptor、DelegatePerTargetObjectIntroductionInterceptor
、MethodBeforeAdviceInterceptor、AspectJAroundAdvice、AspectJAfterAdvice
*/
return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
}
}
这是一个递归方法,递归执行拦截器方法。根据集合下标依次执行。当执行到最后一个拦截器,就是递归的出口,直接执行目标对象方法。
拿到一个拦截器,判断是否为 InterceptorAndDynamicMethodMatcher (内部框架类,将 MethodInterceptor 实例与 MethodMatcher 组合在一起)
如果不是的话,那么直接执行拦截器方法,并且带着当前 ReflectiveMethodInvocation 对象;
我们的拦截方法会被解析成 MethodInterceptor 所以这个分支不会走。
比如我们的前置增强对应的实例为:org.springframework.aop.aspectj.AspectJMethodBeforeAdvice
那么就会进入这个拦截器的方法
// 该方法由 MethodInterceptor 提供
@Override
public Object invoke(MethodInvocation mi) throws Throwable {
this.advice.before(mi.getMethod(), mi.getArguments(), mi.getThis());
return mi.proceed();
}
首先执行增强方法,然后再继续执行拦截链上的下一个拦截方法。