前言
在这篇博文:【小家Spring】详解Spring AOP中底层代理模式之JdkDynamicAopProxy和CglibAopProxy(ObjenesisCglibAopProxy)的源码分析
我们已经能够知道了,代理对象创建好后,其实最终的拦截工作都是交给了MethodInvocation,JDK交给:ReflectiveMethodInvocation,CGLIB交给CglibMethodInvocation
备注:此处所说的MethodInvocation是AOP联盟包里的,也就是org.aopalliance.intercept.MethodInvocation。
AOP联盟包里和cglib包里都有的叫:MethodInterceptor,不要弄混了。
org.aopalliance.intercept.Joinpoint
首先需要注意的是,一般我们会接触到两个Joinpoint
1.org.aspectj.lang.JoinPoint:该对象封装了SpringAop中切面方法的信息,在切面方法中添加JoinPoint参数,可以很方便的获得更多信息。(一般用于@Aspect标注的切面的方法入参里),它的API很多,常用的有下面几个:
1. Signature getSignature(); :封装了署名信息的对象,在该对象中可以获取到目标方法名,所属类的Class等信息
2. Object[] getArgs();:传入目标方法的参数们
3. Object getTarget();:被代理的对象(目标对象)
4. Object getThis();:该代理对象
备注:ProceedingJoinPoint对象是JoinPoint的子接口,该对象只用在@Around的切面方法中
2.org.aopalliance.intercept.Joinpoint是本文的重点,下面主要看看它的解释和相关方法:
// 此接口表示运行时的连接点(AOP术语) (和aspectj里的连接点意思有点像) public interface Joinpoint { // 执行此拦截点,并进入到下一个连接点 Object proceed() throws Throwable; // 返回保存当前连接点静态部分【的对象】。 这里一般指的target Object getThis(); // 返回此静态连接点 一般就为当前的Method(至少目前的唯一实现是MethodInvocation,所以连接点得静态部分肯定就是本方法喽) AccessibleObject getStaticPart(); }
org.aopalliance.intercept.Invocation
它的中文意思:祈祷; 乞求
,它继承自Joinpoint
。
这个类没有同名的,只有的aopalliance
里有。
// 此接口表示程序中的调用~ // 该调用是一个可以被拦截器拦截的连接点 public interface Invocation extends Joinpoint { // 获得参数们。比如方法的入参们 Object[] getArguments(); }
org.aopalliance.intercept.MethodInvocation
接口到了这一层,就比较具象了。它表示方法的执行器
,显然就是和Method方法有关喽
// 方法调用时,对这部分进行描述 public interface MethodInvocation extends Invocation { // 返回正在被调用得方法~~~ 返回的是当前Method对象。 // 此时,效果同父类的AccessibleObject getStaticPart() 这个方法 Method getMethod(); }
MethodInvocation
作为aopalliance
里提供的最底层接口了。Spring提供了相关的实现,如下图:
Spring自己也定义了一个接口,来进行扩展和统一管理:ProxyMethodInvocation
org.springframework.aop.ProxyMethodInvocation
这个接口是Spring提供的对aopalliance里MethodInvocation的继承扩展接口
// 这是Spring提供的对MethodInvocation 的一个扩展。 // 它允许访问 方法被调用的代理对象以及其它相关信息 public interface ProxyMethodInvocation extends MethodInvocation { // 返回代理对象 Object getProxy(); // 克隆一个,使用的Object得clone方法 MethodInvocation invocableClone(); MethodInvocation invocableClone(Object... arguments); // 设置参数 增强器、通知们执行的时候可能会用到 void setArguments(Object... arguments); // 添加一些属性kv。这些kv并不会用于AOP框架内,而是保存下来给特殊的一些拦截器实用 void setUserAttribute(String key, @Nullable Object value); @Nullable Object getUserAttribute(String key); }
下面我们就是主菜了,Spring给我们提供的唯一(其实算唯二吧)的实现类,它执行着拦截的核心逻辑。会让所有的通知器都执行~~
ReflectiveMethodInvocation
Reflective中文意思:可被反射的
显然它作为实现类,需要实现包括父接口在内的所有的方法们。
它也是JdkDynamicAopProxy最终执行时候new出来的执行对象,话不多说,下面看看具体的逻辑吧~~
public class ReflectiveMethodInvocation implements ProxyMethodInvocation, Cloneable { protected final Object proxy; // 代理对象 @Nullable protected final Object target; // 目标对象 protected final Method method; // 被拦截的方法 protected Object[] arguments = new Object[0]; @Nullable private final Class<?> targetClass; @Nullable private Map<String, Object> userAttributes; protected final List<?> interceptorsAndDynamicMethodMatchers; // currentInterceptorIndex初始值为 -1 private int currentInterceptorIndex = -1; // 唯一的构造函数。注意是protected 相当于只能本包内、以及子类可以调用。外部是不能直接初始化的此对象的(显然就是Spring内部使用的类了嘛) //invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain); // proxy:代理对象 // target:目标对象 // method:被代理的方法 // args:方法的参数们 // targetClass:目标方法的Class (target != null ? target.getClass() : null) // interceptorsAndDynamicMethodMatchers:拦截链。 this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass)这个方法找出来的 protected ReflectiveMethodInvocation( Object proxy, @Nullable Object target, Method method, @Nullable Object[] arguments, @Nullable Class<?> targetClass, List<Object> interceptorsAndDynamicMethodMatchers) { this.proxy = proxy; this.target = target; this.targetClass = targetClass; // 找到桥接方法,作为最后执行的方法。至于什么是桥接方法,自行百度关键字:bridge method // 桥接方法是 JDK 1.5 引入泛型后,为了使Java的泛型方法生成的字节码和 1.5 版本前的字节码相兼容,由编译器自动生成的方法(子类实现父类的泛型方法时会生成桥接方法) this.method = BridgeMethodResolver.findBridgedMethod(method); // 对参数进行适配 this.arguments = AopProxyUtils.adaptArgumentsIfNecessary(method, arguments); this.interceptorsAndDynamicMethodMatchers = interceptorsAndDynamicMethodMatchers; } @Override public final Object getProxy() { return this.proxy; } @Override @Nullable public final Object getThis() { return this.target; } // 此处:getStaticPart返回的就是当前得method @Override public final AccessibleObject getStaticPart() { return this.method; } // 注意:这里返回的可能是桥接方法哦 @Override public final Method getMethod() { return this.method; } @Override public final Object[] getArguments() { return this.arguments; } @Override public void setArguments(Object... arguments) { this.arguments = arguments; } // 这里就是核心了,要执行方法、执行通知、都是在此处搞定的 // 这里面运用 递归调用 的方式,非常具有技巧性 @Override @Nullable public Object proceed() throws Throwable { // currentInterceptorIndex初始值为 -1 如果执行到链条的末尾 则直接调用连接点方法 即 直接调用目标方法 if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) { // 这个方法相当于调用了目标方法~~~下面会分析 return invokeJoinpoint(); } // 获取集合中的 MethodInterceptor(并且currentInterceptorIndex + 1了哦) Object interceptorOrInterceptionAdvice = this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex); //InterceptorAndDynamicMethodMatcher它是Spring内部使用的一个类。很简单,就是把MethodInterceptor实例和MethodMatcher放在了一起。看看在advisor chain里面是否能够匹配上 if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) { InterceptorAndDynamicMethodMatcher dm = (InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice; // 去匹配这个拦截器是否适用于这个目标方法 试用就执行拦截器得invoke方法 if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) { return dm.interceptor.invoke(this); } else { // 如果不匹配。就跳过此拦截器,而继续执行下一个拦截器 // 注意:这里是递归调用 并不是循环调用 return proceed(); } } else { // 直接执行此拦截器。说明之前已经匹配好了,只有匹配上的方法才会被拦截进来的 // 这里传入this就是传入了ReflectiveMethodInvocation,从而形成了一个链条了 return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this); } } // 其实就是简单的一个:method.invoke(target, args); // 子类可以复写此方法,去执行。比如它的唯一子类CglibAopProxy内部类 CglibMethodInvocation就复写了这个方法 它对public的方法做了一个处理(public方法调用MethodProxy.invoke) @Nullable protected Object invokeJoinpoint() throws Throwable { // 此处传入的是target,而不能是proxy,否则进入死循环 return AopUtils.invokeJoinpointUsingReflection(this.target, this.method, this.arguments); } @Override public MethodInvocation invocableClone() { Object[] cloneArguments = this.arguments; if (this.arguments.length > 0) { // Build an independent copy of the arguments array. cloneArguments = new Object[this.arguments.length]; System.arraycopy(this.arguments, 0, cloneArguments, 0, this.arguments.length); } return invocableClone(cloneArguments); } @Override public MethodInvocation invocableClone(Object... arguments) { if (this.userAttributes == null) { this.userAttributes = new HashMap<>(); } try { ReflectiveMethodInvocation clone = (ReflectiveMethodInvocation) clone(); clone.arguments = arguments; return clone; } catch (CloneNotSupportedException ex) { throw new IllegalStateException( "Should be able to clone object of type [" + getClass() + "]: " + ex); } } @Override public void setUserAttribute(String key, @Nullable Object value) { if (value != null) { if (this.userAttributes == null) { this.userAttributes = new HashMap<>(); } this.userAttributes.put(key, value); } else { if (this.userAttributes != null) { this.userAttributes.remove(key); } } } @Override @Nullable public Object getUserAttribute(String key) { return (this.userAttributes != null ? this.userAttributes.get(key) : null); } public Map<String, Object> getUserAttributes() { if (this.userAttributes == null) { this.userAttributes = new HashMap<>(); } return this.userAttributes; } @Override public String toString() { // Don't do toString on target, it may be proxied. StringBuilder sb = new StringBuilder("ReflectiveMethodInvocation: "); sb.append(this.method).append("; "); if (this.target == null) { sb.append("target is null"); } else { sb.append("target is of class [").append(this.target.getClass().getName()).append(']'); } return sb.toString(); } }