spring复习:(38)ProxyFactoryBean中使用jdk动态代理生成代理对象时,业务方法调用时的执行流程

news2024/11/26 0:47:58

在这里插入图片描述
当调用代理对象的业务方法时,会直接执行JdkDynamicAopProxy类的invoke方法

	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		Object oldProxy = null;
		boolean setProxyContext = false;

		TargetSource targetSource = this.advised.targetSource;
		Object target = null;

		try {
			if (!this.equalsDefined && AopUtils.isEqualsMethod(method)) {
				// 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...
				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.
			target = targetSource.getTarget();
			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 {
				// We need to create a method invocation...
				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);
			}
		}
	}

其中
在这里插入图片描述

用来获得拦截器链,getInterceptorAndDynamicInterceptionAdvice代码如下:

	public List<Object> getInterceptorsAndDynamicInterceptionAdvice(Method method, @Nullable 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;
	}

调用之后chain中就保存了Advisor的list.
然后执行下边的代码:
在这里插入图片描述
其中调用的proceed方法代码如下:

	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.
			return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this);
		}
	}

其中return ((MethodInterceptor) interceptorOrInterceptionAdvice).invoke(this); 这个Invoke方法会执行我们自己定义的某个advisor
在这里插入图片描述
Object obj = invocation.proceed会进入如下代码片段来执行:
在这里插入图片描述
其调用的invokeJoinPoint()方法的代码如下:
在这里插入图片描述
其所调用的invokeJoinpointUsingReflection的代码如下:
在这里插入图片描述
可见其直接调用了method.invoke方法。这个invoke方法返回之后接着执行advisor的后边的逻辑
在这里插入图片描述
整个业务方法调用流程结束。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/764881.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Matter初探

这是运行gn_build.sh之后输出的日志 Script started on 2023-07-17 09:39:460800 ]0;userubuntu: ~/Matter/connectedhomeip[01;32muserubuntu[00m:[01;34m~/Matter/connectedhomeip[00m$ source gn_build.sh [0;33m.--------------------------------[0m [0;33m-- Environmen…

【项目 进程2】2.3 进程创建 2.4父子进程虚拟地址空间 2.5GDB多进程调试

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 2.3 进程创建2.4 父子进程虚拟地址空间父子进程之间的关系&#xff1a; 2.5 GDB多进程调试 2.3 进程创建 系统允许一个进程创建新进程&#xff0c;新进程即为子进程…

特征缩放(归一化处理)

在我们面对多维特征问题的时候&#xff0c;我们要保证这些特征都具有相近的尺度&#xff0c;这将帮助梯度下降算法更快地收敛。 以房价问题为例&#xff0c;假设我们使用两个特征&#xff0c;房屋的尺寸和房间的数量&#xff0c;尺寸的值为 0-2000平方英尺&#xff0c;而房间数…

CAPL(vTESTStudio) - CAPL实现CANCANFD接收

诊断作为CAN&CANFD总线测试中最大也是很重要的一块内容,虽然测试过程比较简单,但是作为诊断接收函数,我想大家在测试中都会遇到多种多样的自研函数,经过多年的工作,我也是一直希望写出一个能够适配我所能想到的所有情况的诊断应答接收,以下函数是我最近对于诊断接收函…

欧姆龙cp11以太网设置连接力控方法

JM-ETH-CP转以太网模块采用即插即用设计&#xff0c;不占用 PLC 通讯口&#xff0c;即编程软件/上位机软件通过以太网对 PLC 数据监控的同时&#xff0c;触摸屏可以通过复用接口与 PLC 进行通讯。捷米特JM-ETH-CP转以太网模块支持工控领域内绝大多数 SCADA 软件&#xff0c;支持…

大语言模型的预训练[1]:基本概念原理、神经网络的语言模型、Transformer模型原理详解、Bert模型原理介绍

大语言模型的预训练[1]:基本概念原理、神经网络的语言模型、Transformer模型原理详解、Bert模型原理介绍 1.大语言模型的预训练 1.LLM预训练的基本概念 预训练属于迁移学习的范畴。现有的神经网络在进行训练时&#xff0c;一般基于反向传播&#xff08;Back Propagation&…

如何免费试用阿里云上资源搭建ChatGLM2+langchain

如何免费试用阿里云上资源搭建ChatGLM2langchain 1.找到免费试用&#xff0c;搜索PAI 2.试用PAI-DSW和NAS 3.找到这个平台打开 4.创建工作空间和实例 这里已经创建过了&#xff0c;没有图 5.对着视频一步一步走

浅析Java编程中类和对象的定义

浅析Java编程中类和对象的定义 1&#xff0c;什么是类&#xff1f; 答&#xff1a;类是客观存在的&#xff0c;抽象的&#xff0c;概念的东西。 2&#xff0c;什么事对象&#xff1f; 答&#xff1a;对象是具体的&#xff0c;实际的&#xff0c;代表一个事物。例如&#xff…

SpringCloud(一)微服务项目搭建

一、简介 SpringCloud是Spring提供的一套分布式解决方案&#xff0c;集合了一些大型互联网公司的开源产品&#xff0c;包括诸多组件&#xff0c;共同组成SpringCloud框架。并且&#xff0c;它利用Spring Boot的开发便利性巧妙地简化了分布式系统基础设施的开发&#xff0c;如服…

网络安全—信息安全—黑客技术(学习笔记)

一、什么是网络安全&#xff1f; 网络安全可以基于攻击和防御视角来分类&#xff0c;我们经常听到的 “红队”、“渗透测试” 等就是研究攻击技术&#xff0c;而“蓝队”、“安全运营”、“安全运维”则研究防御技术。 无论网络、Web、移动、桌面、云等哪个领域&#xff0c;都…

【iOS】探索ARC的实现

ARC ARC在编译期和运行期做了什么&#xff1f;编译期&#xff1a;运行期&#xff1a;block 是如何在 ARC 中工作的&#xff1f; ARC的实现分析__strong自己生成并持有storeStrongSideTable散列表objc_retainobjc_releasesidetable_releaseretainCount非自己生成并持有 ARC在编译…

打包python文件成.exe程序

不带环境打包程序 &#xff0c;下载后的程序需要下载环境才能正常运行 -w:隐藏命令行窗口 -i:添加ico图标文件 最后写入参数代表程序的入口

C#图片处理

查找图片所在位置 原理&#xff1a;使用OpenCvSharp对比查找小图片在大图片上的位置 private static System.Drawing.Point Find(Mat BackGround, Mat Identify, double threshold 0.8) {using (Mat res new Mat(BackGround.Rows - Identify.Rows 1, BackGround.Cols - Iden…

【LeetCode热题100】哈希篇

两数之和 给定一个整数数组 nums 和一个整数目标值 target&#xff0c;请你在该数组中找出 和为目标值 target 的那 两个 整数&#xff0c;并返回它们的数组下标。 你可以假设每种输入只会对应一个答案。但是&#xff0c;数组中同一个元素在答案里不能重复出现。 你可以按任…

短视频抖音账号矩阵系统源码开发分享

引用&#xff1a;MySQL数据库&#xff0c;NGINX&#xff0c;PHP7.4&#xff0c;MySQL5.7&#xff0c;redis 媒体组件 组件 描述 image 图片 图片。支持 JPG、PNG、SVG、WEBP、GIF 等格式。 video 视频 视频组件。相关 API 请参考 tt.createVideoContext。 开发背景&…

Fiddler的使用方法介绍

FIDDLER下载地址fiddler Fiddler可以帮您记录&#xff0c;调试Microsoft Internet Explorer与Web应用程序的交互&#xff0c;找到Web程序运行性能的瓶颈&#xff0c;还有如查看向Web服务器发送cookies的内容&#xff0c;下载内容的大小等功能。 说多一点是&#xff0c;Fiddler站…

docker-compose部署sentinel-dashboard-1.8.5

一、创建文件夹 mkdir -p /docker/alibaba/sentinel/{config,data,logs} 二、拷贝jar包进sentinel目录下 三、Dockerfile文件 FROM openjdk:8-jre MAINTAINER yh COPY ./sentinel-dashboard.jar /app.jar EXPOSE 8718 ENTRYPOINT ["java", "-jar", &quo…

【Linux C】fseek函数使用小结

0x00 前言 演示使用的Linux版本&#xff08;#cat /etc/issue&#xff09;&#xff1a;Ubuntu 18.04.6 LTS \n \l 最后更新日期&#xff1a;2023.7.17 0x01 fseek函数使用小结 1.函数描述 设置stream文件的位置指针偏移到指定位置1。 2.声明 #include <stdio.h> in…

LVS—Linux Virtual Server

集群和分布式 系统性能拓展方式&#xff1a; Scale UP&#xff1a;垂直拓展&#xff0c;提高单个服务器的性能&#xff0c;如增加CPU、内存等&#xff0c;单台服务器的性能是有上限的&#xff0c;不可能无限制垂直拓展。Scale Out&#xff1a;水平拓展&#xff0c;增加设备&a…

用Python采集电商平台商品数据进行可视化分析

目录标题 前言环境使用:模块使用:基本流程思路:代码展示获取数据扩展知识数据可视化 尾语 前言 嗨喽~大家好呀&#xff0c;这里是魔王呐 ❤ ~! 环境使用: python 3.8 解释器 pycharm 编辑器 模块使用: 第三方模块 需要安装 requests —> 发送 HTTP请求 内置模块 不需…