【源码】Spring AOP 3 Joinpoint

前言

本章节,我们解析 Joinpoin 接口,它是对整个 AOPJoin point 的概念的抽象

接口

Joinpoint

public interface Joinpoint {

	// 执行方法到下一个拦截器
	Object proceed() throws Throwable;

	// 获取 target object
	Object getThis();
	
	// 返回 static part
	AccessibleObject getStaticPart();

}

Interceptors chain 的传递基于 proceed() 方法。此处的 “static part” 概念比较抽象,我们姑且将其理解为 “method
Joinpoint

Invocation

public interface Invocation extends Joinpoint {

	Object[] getArguments();

}

拓展了 Joinpoint ,并提供了获取参数的方法。
Invocation
如之前说过的,此处我们忽略 ConstructorInvocation,只看 MethodInvocation

MethodInvocation

public interface MethodInvocation extends Invocation {

	Method getMethod();

}

针对方法的抽象,提供了 getMethod() 方法。此时,getMethod() 等同于 getStaticPart()

MethodInvocation
可以发现,整个 Joinpoint 的结构还是比较简单清晰的

ProxyMethodInvocation

public interface ProxyMethodInvocation extends MethodInvocation {

	// 获取代理对象
	Object getProxy();
	
	// 克隆,如果克隆之前 proceed 方法还未执行,则会执行多次
	MethodInvocation invocableClone();

	MethodInvocation invocableClone(Object... arguments);

	void setArguments(Object... arguments);

	/**
	 * 自定义属性,不用于 AOP 框架本身,而是作为 invocation 对象的一部分,
	 * 供给指定的拦截器使用
	 */
	void setUserAttribute(String key, @Nullable Object value);

	@Nullable
	Object getUserAttribute(String key);

}

MethodInvocation 的拓展,支持对代理对象的访问
ProxyMethodInvocation
该接口有且仅有一(两)个实现类。众所周知,Spring 实现代理的方式只有两种

  • JDK动态代理
  • CGLIB代理

而这两个实现类就分别是上述两种代理方式对应的 Invocation

实现类

ReflectiveMethodInvocation

重点看看核心proceed() 方法

	@Override
	@Nullable
	public Object proceed() throws Throwable {
		
		// 计数器初始值为-1,此处表示拦截链执行完后就执行目标方法了(基于反射)
		if (this.currentInterceptorIndex == this.interceptorsAndDynamicMethodMatchers.size() - 1) {
			return invokeJoinpoint();
		}

		// 取出并递增计数器
		Object interceptorOrInterceptionAdvice =
				this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);
		
		/**
		 * 此处判断该 interceptor 是否是 InterceptorAndDynamicMethodMatcher
		 * (该类内部实际也维护了一个 MethodInterceptor)
		 * 此处如果匹配成功则执行内部 MethodInterceptor 的 invoke 方法
		 * 否则跳过该 interceptor 并 proceed 执行下一个 interceptor
		 */ 
		if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
			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 {
				return proceed();
			}
		}
		else {
			/**
			 * 此处就是我们眼熟的 MethodInterceptor,调用它的 invoke 方法并传入 this
			 * 实际上,invoke 内部又调用了 this.proceed() 方法
			 * e.g.
			 * 	public Object invoke(MethodInvocation mi) throws Throwable {
			 * 		Object retVal = mi.proceed();
			 * 		this.advice.afterReturning(retVal, mi.getMethod(), mi.getArguments(), mi.getThis());
			 * 		return retVal;
			 * 	}
			 * 	于是巧妙地形成了递归,配合计数器,最终在 interceptors 执行完后调用目标方法
			 */
			return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
		}
	}
  • this.interceptorsAndDynamicMethodMatchers 持有所有的拦截器链,其内部会依次调用它们的 invoke 方法
  • 根据之前 MethodInterceptor 的相关学习,可以发现 MethodInterceptor#invokeMethodInvocation#proceed 最终形成递归

CglibMethodInvocation

CglibMethodInvocationReflectiveMethodInvocation 的一个拓展,主要是带来性能上的提升,细节我也不清楚,略

类图

joinpoint

序列图

proceed

总结

整个 Joinpoint 的抽象还是比较清晰简单,重点是其实现类 ReflectiveMethodInvocationpreceed() 方法,巧妙的将 MethodInterceptorMethodInvocation 结合了起来

截止当前, aopalliance 下的抽象已经解析完了,下一章节了解下 Spring AOP 下的 Pointcut 抽象体系

上一篇:【源码】Spring AOP 2 Advice
下一篇:【源码】Spring AOP 4 Pointcut

参考

【小家Spring】探索Spring AOP中aopalliance的Joinpoint、MethodInvocation、Interceptor、MethodInterceptor…

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值