Spring AOP 实例解析(InvocationHandler 的invoke的proxy 参数作用)

Spring代理模式深度解析:从AOP原理到事务模拟实战 代理模式是面向对象编程中一种核心的结构型设计模式,它通过提供一个代理对象来控制对原始对象的访问。其核心原理在于在不修改原始对象代码的前提下,为方法调用添加额外的逻辑,如日志、事务、安全控制等,这体现了面向切面编程(AOP)的思想。这种机制的技术价值在于实现了关注点分离,提升了代码的模块化、可维护性和可扩展性,是构建大型、复杂系统的基石。在Java生态中,Spring框架的AOP功能正是代理模式的典范应用,它广泛应用于声明式事务管理(@Transactional)、缓存(@Cacheable)和日志记录等横切 阅读详情

代理模式:为其他对象提供一种代理以便控制对这个对象的访问(所谓控制,就是可以在其调用行为,前后分别加入一些操作)。代理模式分类:1.静态代理(其实质是类的继承,比较容易理解)2.动态代理。

用JDK 动态代理实现面向切面编程(还有CGLIB 也可实现动态代理,且不需要真实对象类实现接口,但真实对象不能是final 类),以下Demo 实现在特定方法前后添加日志和事务的的功能。

1)Proxy 类 (真实对象的代理) 的三个参数

    前两个参数用于生成$Proxy 的构造器,此构造器再以invocationHandler 为参数生成$Proxy 实例。

  • classLoader: 类加载器,它由真实对象userService 得到,但其实跟userService 不是一一对应的关系;用任何一个对象都可以用同样的方法得到一样的类加载器;既然如此,用测试类本身也可以得到类加载器:this.getClass().getClassLoader(),再把this 省略,就变成了getClass().getClassLoader()。
    类加载器打印出来就是:sun.misc.Launcher$AppClassLoader@18b4aac2
  • interfaces: 接口数组,真实对象userService 所实现的所有接口。Proxy 用类加载器和接口数组这两个参数得到动态生成的Proxy 的Class 对象(getProxyClass0(loader, intfs)),再用此Class 对象获取其构造器(cl.getConstructor(constructorParams)),由构造器生成Proxy 实例(cons.newInstance(new Object[]{h}), 此处的h 就是Proxy 第三个参数invocationHandler). 
  • invocationHandler: 直译是调用处理器,它这个对象本质是Proxy 类的代理,也就是真实对象的代理 的代理。Proxy类实现了真实对象的接口,所以它的对象可以调用真实对象的方法,调用时是指派invocationHandler 去实际执行系统增强业务(即日志、事务等) 和真实业务。

2)InvocationHandler 的invoke 三个参数的作用

  • proxy: 就是Proxy 的一个动态实例,用Idea debug 显示为:{$Proxy4@862} com.qf.service.impl.UserServiceImpl@5a8806ef. 这个参数在invoke 方法体内可以完全不用,所以很难理解它的作用,甚至知乎、Stackoverflow 上的回答都感觉不太对。Stackoverflow 上一个回答说作用是可以将代理对象返回以进行连续调用,并写了demo(https://stackoverflow.com/questions/22930195/understanding-proxy-arguments-of-the-invoke-method-of-java-lang-reflect-invoca),难道不需要连续调用的话就没用了吗?又查了很多资料,终于找到了一个比较符合逻辑的解释:invoke 第二个参数是method 怎么来的?$Proxy 动态实例 (即第一个参数proxy) 生成后(是class 文件),通过反向编译,可以看到里面有如下一段静态代码块(来源:(http://rejoy.iteye.com/blog/1627405)),也就是说只有proxy 实例在InvocationHandler 实现类里加载才能产生第二个参数method (静态代码块是虚拟机加载类的时候执行的,而且只执行一次),所以$Proxy 实例要把自己传给InvocationHandler 的invoke 方法。
m3 = Class.forName("dynamic.proxy.UserService").getMethod("add", new Class[0]);

    InvocationHandler 源码中对proxy 的注释:the proxy instance that the method was invoked on

  • method: 真实对象要实现的业务方法,由$Proxy 实例的静态代码块得到。
  • args: 第二个参数method 的参数。

3)两个概念:系统增强服务(日志、事务、权限等) 与系统真实业务分离,放到 InvocationHandler 实现类invoke 方法里面的 这些出代码片段就是一个切面,本文Demo 中真实业务add() 就是切入点。


以下为InvocationHandler 实现类和测试类(含创建$Proxy 动态实例) 的代码。

public class DynamicProxy implements InvocationHandler {
	private TransactionManager tx;
	private LoggerManager log;
	private Object object;
 
	public DynamicProxy() {
	}
        //object 参数为真实对象,此例中为userService 对象
	public DynamicProxy(TransactionManager tx, LoggerManager log, Object object) {
		this.tx = tx;
		this.log = log;
		this.object = object;
	}
	@Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
		tx.begin();
		log.beginLog();
		Object invoke = method.invoke(object, args);
		log.endLog();
		tx.commit();
		return invoke;
	}
}
        @Test
	public void testDynamicAOP(){
		LoggerManager log = new LoggerManager();
		TransactionManager tm = new TransactionManager();
		IUserService userService = new UserServiceImpl();
		ClassLoader loader = userService.getClass().getClassLoader();
		Class<?>[] interfaces = userService.getClass().getInterfaces();
		InvocationHandler handler = new DynamicProxy(tm, log, userService);
		IUserService userServiceProxy = (IUserService) Proxy.newProxyInstance(loader, interfaces, handler);
		userServiceProxy.add(new User("Rock"));
	}

相关链接:
(https://stackoverflow.com/questions/22930195/understanding-proxy-arguments-of-the-invoke-method-of-java-lang-reflect-invoca)

(http://rejoy.iteye.com/blog/1627405)

AUTOSAR进阶图解==>AUTOSAR_SWS_CANStateManager AUTOSAR CAN状态管理器(CanSM)摘要 CanSM是AUTOSAR通信栈中的关键模块,负责管理CAN网络状态和模式转换。主要功能包括: 控制CAN控制器/收发器工作模式(STARTED/STOPPED,NORMAL/STANDBY) 处理三种网络状态(全通信、静默通信、无通信)之间的转换 监控和处理总线关闭(Bus-Off)事件 与ComM、CanIf、BswM等模块协同工作 CanSM通过状态机管理网络状态转换,支持可配置的总线关闭恢复策略。它为每个CAN网络维护独立的状态机,实现网络状态的精 阅读详情

相关推荐

【邻接表存图模板】vector邻接表、数组邻接表、链式前向星

一、目录 一、目录 二、前言 三、邻接表“详解” (一)边的信息 (二)几种邻接表的实现方法“详解” 1.数组邻接表 代码 2.vector邻接表 代码 vector邻接表还有一种魔性写法: 3.链式前向星 代码 四、总结 二、前言 本来之前自己太弱了,一直只会用邻接矩阵,后来发现邻接表才是主流... 参考&特别鸣谢: https://www.cnblog...

十里寒塘路♣烟花一半醒 3113

InvocationHandler中invoke()方法的调用问题

JDK动态代理原理

立身以力学为先,力学以读书为本。 —郑耕老《劝学》 1192

用Python实现古诗词填字游戏(三)

古诗词做填字游戏的第三部分代码,也是最核心的部分。实现对诗文和关键字的选定,并确定文字的输出位置。

PosPro的专栏 6117

JDK实现动态代理,以及InvocationHandler接口invoke()方法的三个参数的作用

先上代码: 首先是要被代理的接口: /** * 被代理的主体需要实现的接口 */ public interface Subject { String doSomething(String thingsNeedParm); String doOtherNotImportantThing(String otherThingsNeedParm); } 然后是代理接口的...

a907691592的博客 6804

手把手教你用Matlab实现Copula函数:从理论到代码的完整指南

本文提供了一份在MATLAB中实现Copula函数的完整实战指南。从理解Sklar定理和常见Copula家族(如高斯、t、Clayton)的核心概念出发,详细讲解了数据预处理、边缘分布拟合、概率积分变换等关键步骤。通过具体代码示例,手把手演示了Copula模型的拟合、评估、蒙特卡洛模拟,并进阶应用于金融风险度量(如VaR计算)和条件分布分析,帮助读者掌握这一强大的多变量依赖建模工具。

y9z0a1b的博客 952

使用Power Apps实现SharePoint Online列表的下拉菜单的级联选择

在SharePoint列表中添加数据的时候,下拉菜单的级联选择一直是一个非常实用的功能,尤其是有很多数据的情况,级联选择可以根据上一层的选择,自动过滤下一层的选择,方便用户查找和选择准确的信息。一个最常用的情景是选择供应商的地区和国家,例如有三个列表,一个是供应商所在的大洲,一个是国家,一个是供应商。当用户选择州的时候,会自动列出属于这个州的国家。避免用户迷失在大量的数据中。 这里展示一下如何在...

shrenk的专栏 7808

spring

使用ApplicationContext获取bean的三种方式使用@Autowired时,它会先使用byType自动注入进行找对应类型的bean,如果有两个相同类型的bean时,那么它会按byName去找对应的bean,如果没有会报错;在对于有多个类型的bean时,可以使用@Qualifier(“id”)来指定自动注入哪个bean。

m0_51906928的博客 986

手把手教你用C#和LibUsbDotNet实现USB设备通信(含完整代码示例)

本文详细介绍了如何使用C#和LibUsbDotNet库实现USB设备通信,包括设备识别、连接建立、同步/异步数据读写等核心操作。通过完整的代码示例,开发者可以快速掌握USB通信的关键技术,适用于工业自动化、医疗设备等多种场景。重点讲解了数据读写优化和错误处理技巧,帮助提升通信效率和可靠性。

a3b4c5的博客 703

InvocationHandler的invoke方法的第一个参数问题

今天有同事问起,动态代理中的InvocationHandler的invoke方法的第一个参数。是代理类还是委托类(即被代理类). 其实这个参数是代理类。我们看一下生成的代理类就会明白: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 publicinterfaceProxyInf { publi...

weixin_34249678的博客 1352

Android PMS——概述(一)

PMS(Package Manager Service)是 Android 操作系统的一个重要组件,它负责管理应用程序的包信息以及与应用程序的安装、卸载、权限控制等相关功能,确保应用程序的安全性和稳定性。 Android PMS 负责维护一个应用程序包的清单信息,该清单是一个 XML 文件,包含应用程序的各种元数据,例如应用程序的包名、版本号、权限要求、组件信息等。PMS通过访问该清单文件来获取应用程序的信息。 此外,Android PMS 还负责应用程序的安装和卸载。在安装应用

小旭的专栏 1664

069、自动曝光(AE)测光策略:全局/中心/点测光与曝光时间增益分配

本文深入探讨了自动曝光(AE)测光策略的技术细节与实际应用。作者通过多个真实案例(手机前置摄像头、车载ADAS、安防监控等)分析了全局测光、中心测光和点测光的优缺点,指出不同场景应采用不同策略。重点剖析了曝光时间与增益分配的"跷跷板效应",提出要根据传感器特性选择最优分配方案。文章强调测光策略应动态调整,并给出5条实用建议:结合场景切换测光模式、关注传感器增益拐点、点测光需防抖处理、全局测光不宜迷信、调试要观察亮度直方图。最后指出AE调试需要结合具体硬件特性进行实测优化,没有通用解决方案。

zzfmlxs的博客 100

JDK动态代理解析,InvocationHandler的第一个参数的解析

详解JDK动态代理,InvocationHandler中invoke()方法的第一个参数的意义,终于弄懂了

这是我的笔记本,记录学习历程,分享学习经验,菜鸡一枚,感谢支持! 1108

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

彻底吃透JDK动态代理:手写模拟底层+源码解析,搞懂invoke方法与proxy参数

本文深入解析了JDK动态代理的实现原理,通过手写模拟代理类$Proxy0的方式揭示其核心机制。主要内容包括:1)动态代理必须基于接口实现,定义了Star接口和BigStar被代理类;2)关键揭示了代理类将所有方法调用都转发给InvocationHandler的invoke()方法,并将代理对象自身作为第一个参数传入;3)通过自定义InvocationHandler实现代理逻辑,其中proxy参数即为代理对象本身。文章通过代码示例和原理分析,完整展现了JDK动态代理的工作流程和底层设计思想。

weixin_68315058的博客 538

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

Java动态代理InvocationHandler和Proxy学习笔记

1.InvocationHandler接口是proxy代理实例的调用处理程序实现的一个接口,每一个proxy代理实例都有一个关联的调用处理程序;在代理实例调用方法时,方法调用被编码分派到调用处理程序的invoke方法。 看下官方文档对InvocationHandler接口的描述: {@code InvocationHandler} is the interface implement...

OceanSky的专栏 13万+

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

Spring AOP 基石:JDK 动态代理原理与实战解析(spring-aop-jdkProxy)

JDK 动态代理是 Spring AOP 的两大代理基石之一(另一基石为 CGLIB),它基于接口在运行时动态生成代理类,通过 `InvocationHandler` 统一接管方法调用,让日志、权限校验、事务等横切逻辑无须侵入业务代码。本文以 [spring-aop-jdkProxy](https://link.gitcode.com/i/a1ed86e53fe7686d4a7af4ca868ce

gitblog_00439的博客 224

JDK 动态代理实现原理解析:从 Proxy.newProxyInstance 到 $Proxy0 代理类字节码(Source Code Hunter 源码赏析)

本篇围绕 JDK 动态代理的底层实现展开:从 `Proxy.newProxyInstance()` 的调用入口出发,先给出一个完整的增强示例,再借助 `ProxyGenerator` 将运行时生成的代理类字节码反编译出来,逐段剖析 `$Proxy0` 的类结构、静态块、构造器与方法回调,最终把“代理方法 → `super.h.invoke()` → `InvocationHandler.invok

gitblog_01082的博客 424

从源码看 Spring AOP 如何生效:`<aop:aspectj-autoproxy/>` 标签解析与自动代理创建器注册机制

在 Spring 框架中,只需要在 XML 配置文件里写上一行 `<aop:aspectj-autoproxy/>`,基于注解的 Spring AOP 能力就会被激活。这背后隐藏着一条清晰的源码链路:XML 命名空间标签 → 标签解析器(`BeanDefinitionParser`)→ 自动代理创建器(AutoProxyCreator)的注册与属性装配。本文以 [source-code-hunte

gitblog_00337的博客 1077

JDK的Proxy技术实现AOP,InvocationHandler和Proxy详解——Spring AOP(三)

上一章已经讲到了想要完成AOP的设计原理以及要实现AOP功能,得需要使用代理模式: 本章就介绍一个实现动态代理的两种方式之一——JDK中的Proxy技术 AOP实现原理(使用JDK中的Proxy技术实现AOP功能,InvocationHandler和Proxy(Class)详解) AOP技术在企业开发中或多或少都会用到,但用的最多的大概就是做权限系统时,判断用户是否是有权限,有权限就执行该方法,...

方圆几里 3315

全网最强剖析Spring AOP底层原理

本文深入讲解了Spring AOP的核心原理,从静态代理模式入手,通过房东出租房屋的案例形象说明代理模式的运作机制。静态代理虽然直观,但存在类文件过多、维护性差等缺点。随后重点介绍了Spring动态代理的实现方式,详细分析了开发步骤:创建原始对象、定义额外功能、定义切入点和组装切面。文章特别强调了动态代理通过字节码技术在JVM运行时创建代理类的特点,以及相比静态代理在维护性和扩展性上的优势。最后对额外功能中的MethodBeforeAdvice接口及其参数进行了详细解析。全文结合代码示例和示意图,帮助读者深

qq_45832461的博客 2500

很难出错的spring5(六)—— AOP预备知识:静态代理和动态代理

在学习多线程的时候我们学过静态代理,new Thread(new 线程类()).start()的原理就是静态代理。在线程类的run方法里面,我们只写了和线程无任何关系的简单逻辑,new一个对象丢给Thread对象,就能跑起来了!如何创建的线程,如何实现CPU调度线程转为执行状态,都是Thread对象帮我们做的。

qq_44886213的博客 143

源码通透-spring-AOP-4-spring-AOP-invoke调用过程

源码通透-spring-AOP-4-spring-AOP-invoke调用过程 spring version: 5.0.0; jdk: 1.8 文章目录源码通透-spring-AOP-4-spring-AOP-invoke调用过程一、调用概述1.1 JDK代理和CGLIB的调用1.2 调用路径链1.3 JDK和AOP调用比较1.4 JdkDynamicAopProxy和ObjenesisCgli...

arthur.dy.lee的专栏 1784

(二)Spring AOP的实现-Spring AOP拦截器调用的实现

1.Spring AOP通过JDK的Proxy方式或CGLIB方式生成代理对象的时候,相关的拦截器已经配置到代理对象中去了,拦截器在代理对象中起作用是通过对这些方法的回调来完成的。如果使用JDK的Proxy来生成代理对象,需要通过哦InvocationHandler来设计拦截器回调,如果用CGLIB生成代理对象,需要通过DynamicAdvisedInterceptor来完成回调。2.JdkDyn...

qq_22866497的博客 2015

Spring AOP 事务

容器、AOP和事务

2404_88294688的博客 1592

spring aop原理 InvocationHandler Proxy

spring aop是基于spring IOC容器来管理以及使用了JDK自身的动态代理来实现,程序运行时在被切面前后动态进行的一些逻辑处理。   package com.daosheng.component; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import jav...

轻轻草原啊 347
上一篇: InvocationHandler中invoke()方法的调用问题
下一篇: Redisson资料
banlucainiao
博客等级 码龄11年 319粉丝 31原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值