Spring AOP的实现:Spring AOP拦截器调用的实现

上次我说到关于ProxyFactoryBean对象的getObject方法返回了一个代理对象。剩下的AOP实现过程就和jdk的代理模式相同。通过调用这个代理对象的方法(这个方法和目标对象是相同的),但是实际上是调用了invoke方法,通过反射来实现方法的增强。

关于jdk如何实现代理模式的反编译,底层的代码实现过程可以在这个博客中查看

https://blog.csdn.net/u013815218/article/details/52562536(转载)

目录

JDKDynamicAopProxy的invoke拦截

AOP拦截器链的调用

配置通知器


现在我们来看上次说的JdkDynamicAopProxy的getProxy方法的返回值

Proxy.newProxyInstance(classLoader, proxiedInterfaces, this);

其中这个this指的是InvocationHandler对象,通过对这个接口的invoke方法的重写,实现了对目标对象的增强。也就是说我们Proxy对象的代理方法被调用时,JdkDynamicAopProxy的invoke方法作为Proxy对象的回调函数而被触发。那么实际上真正的增强工作都是在JdkDynamicAopProxy中的invoke方法实现了。

JDKDynamicAopProxy的invoke拦截

源代码有100多行,所以我就没有粘贴,可以到

org.springframework.aop.framework.JdkDynamicAopProxy中进行查看。

首先我们要获得目标对象

target = targetSource.getTarget();

之后我们要获得之前我们初始化的拦截器链。

List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

如果没有拦截器链(注意这个地方的拦截器实际上是对方法的增强操作),就直接执行相应的方法。

如果有拦截器的设定,那么需要调用拦截器之后才调用目标对象的方法。

通过构造一个ReflectiveMethodInvocation来实现。

invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);

在拦截器链上执行相应的加强方法。

retVal = invocation.proceed();

这个invocation将我们的拦截器链(也就是一系列的通知器)进行了封装,里面定义了各个加强方法。

书上还有关于目标对象方法的调用

public static Object invokeJoinpointUsingReflection(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) {
			throw new AopInvocationException("AOP configuration seems to be invalid: tried calling method [" +
					method + "] on target [" + target + "]", ex);
		}
		catch (IllegalAccessException ex) {
			throw new AopInvocationException("Could not access method [" + method + "]", ex);
		}
	}

实际上我们可以看到还是调用这个jdk自身的反射机制

	return method.invoke(target, args);

AOP拦截器链的调用

关于AOP链的调用,就是AOP实现的核心部分了

我们需要分析一下这个proceed()方法。

首先我们沿着定义好的拦截器链进行处理

Object interceptorOrInterceptionAdvice =
				this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);

这个是为了递归查找我们合适的拦截器而设定的。

接下来需要对拦截器进行动态匹配,也就是我们之前说的pointcut,匹配正确的切点进行正确的方法加强。

如果不匹配,那么这个proceed方法就会被递归调用。

if (interceptorOrInterceptionAdvice instanceof InterceptorAndDynamicMethodMatcher) {
			// Evaluate dynamic method matcher here: static part will already have
			// been evaluated and found to match.
			InterceptorAndDynamicMethodMatcher dm =
					(InterceptorAndDynamicMethodMatcher) interceptorOrInterceptionAdvice;
			if (dm.methodMatcher.matches(this.method, this.targetClass, this.arguments)) {
				return dm.interceptor.invoke(this);
			}
			else {
				// Dynamic matching failed.
				// Skip this interceptor and invoke the next in the chain.
				return proceed();
			}
		}

配置通知器

首先我们想要知道,在这个proceed()方法中的

Object interceptorOrInterceptionAdvice =
				this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);

这个拦截器链是怎么获取的呢。我们来看一下这个类的构造方法

protected ReflectiveMethodInvocation(
			Object proxy, Object target, Method method, Object[] arguments,
			Class<?> targetClass, List<Object> interceptorsAndDynamicMethodMatchers) {

		this.proxy = proxy;
		this.target = target;
		this.targetClass = targetClass;
		this.method = BridgeMethodResolver.findBridgedMethod(method);
		this.arguments = AopProxyUtils.adaptArgumentsIfNecessary(method, arguments);
		this.interceptorsAndDynamicMethodMatchers = interceptorsAndDynamicMethodMatchers;
	}

 这个参数的配置是我们传入的一个入参。那么回到整个拦截器链的配置过程,

invocation = new ReflectiveMethodInvocation(proxy, target, method, args, targetClass, chain);

一切就都明白了,我们把之前我们获取到chain当做一个参数传给了我们的invocation对象。

List<Object> chain = this.advised.getInterceptorsAndDynamicInterceptionAdvice(method, targetClass);

书上还为我们解释了拦截器如何从AdvisedSupport获得

public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, Class<?> targetClass) {
		MethodCacheKey cacheKey = new MethodCacheKey(method);
		List<Object> cached = this.methodCache.get(cacheKey);
		if (cached == null) {
			cached = this.advisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(
					this, method, targetClass);
			this.methodCache.put(cacheKey, cached);
		}
		return cached;
	}

取得拦截器的工作是由配置好的advisorChainFactory (DefaultAdvisorChainFactory对象)完成的

org.springframework.aop.framework.DefaultAdvisorChainFactory.getInterceptorsAndDynamicInterceptionAdvice(
            Advised config, Method method, Class<?> targetClass)

在这个方法中,我们可以根据书中的代码进行分析。

首先我们的config持有了advisor链。至于为什么持有了advisor链呢,我们需要对原先的代码进行一下追踪。这个查找过程需要去看。

在我们之前创建代理对象的时候,我有提到过这个方法。

org.springframework.aop.framework.ProxyCreatorSupport

protected final synchronized AopProxy createAopProxy() {
		if (!this.active) {
			activate();
		}
		return getAopProxyFactory().createAopProxy(this);
	}

这个类继承了AdvisedSupport类,这就和之前的getInterceptorsAndDynamicInterceptionAdvice对应上了。

继续向上查找ProxyFactoryBean,在这个类中我们可以看到,它继承了ProxyCreatorSupport。而我们在配置它的时候为它声明了相应的advisors,这就是为什么说config已经为我们配置好了相应的advisor链。实际上这一系列的this对象归根到底都是内个最开始的ProxyFactoryBean对象。

具体的拦截器链的加入是通过AdvisorAdapterRegistry这个类来完成的。具体的代码我留作下一篇博客解释。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring AOP中,拦截器责任链处理过程是指当目标方法被多个通知匹配到时,Spring通过引入拦截器链来保证每个通知的正常执行拦截器链是由一系列的拦截器组成的,每个拦截器都负责在目标方法的前后执行特定的逻辑。 在源码中,拦截器责任链的处理过程主要通过MethodInvocation接口来实现。MethodInvocation接口提供了proceed()方法,用于执行拦截器链中下一个拦截器的逻辑。当调用proceed()方法时,会按照拦截器链的顺序依次执行每个拦截器的逻辑,直到达到链的末尾或者某个拦截器决定终止链的执行。 在拦截器责任链处理过程中,每个拦截器可以在目标方法调用前后执行自定义的逻辑。拦截器可以对方法的参数进行检查、修改方法的返回值,或者在方法执行前后记录日志等操作。通过拦截器责任链的处理,Spring AOP能够实现面向切面编程的功能。 需要注意的是,拦截器链的执行顺序是根据拦截器的配置顺序确定的。在Spring的配置文件中,可以通过配置拦截器的顺序来控制拦截器链的执行顺序。这样可以确保每个拦截器按照预期的顺序执行,从而达到期望的功能效果。 总结起来,Spring AOP源码的拦截器责任链处理过程主要通过MethodInvocation接口实现,它通过调用proceed()方法来依次执行拦截器链中每个拦截器的逻辑。拦截器链的执行顺序可以通过配置文件来控制,从而实现面向切面编程的功能。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [Spring AOP源码:拦截器责任链处理过程](https://blog.csdn.net/weixin_45031612/article/details/128806966)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [Spring AOP 自动代理源码 DefaultAdvisorAutoProxyCreator](https://download.csdn.net/download/weixin_38530536/14854229)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [【SpringSpring AOP 源码分析-拦截器链的执行过程(四)](https://blog.csdn.net/qq_46514118/article/details/121912507)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值