[八股]从反射到动态代理

从反射到动态代理

这部分文章将能解答以下问题:

JVM的类加载过程中加载这一阶段做了什么?

讲一下设计模式中的代理模式

动态代理是什么?

Spring是如何实现AOP的?

初识反射

Java反射可以在程序运行时动态加载类并获取类的详细信息,从而操作类的属性和方法。

从jvm的类加载过程讲起,类的加载是将二进制字节码文件加载到内存中,同时在堆中创建一个Class对象作为访问方法区类结构的唯一入口。反射就是通过这个Class对象来获取类的详细信息。

代理

代理模式就是为一个对象提供一个代理,由代理对象来控制对真实对象的访问的设计模式。

根据字节码的创建时机,可分为静态代理和动态代理。

静态代理

静态代理的字节码文件在程序运行前便已经存在了。

以下是静态代理的一个例子。

interface QueryService{int query(int id);
}
class QueryServiceImpl implements QueryService{@Overridepublic int query(int id){return 0;}
}
class QueryServiceProxy implements QueryService{private QueryService target;public QueryServiceProxy(QueryService target){this.target=target;}@Overridepublic int query(int id){before();traget.query(id);}public void before(){Systems.out.println("调用前置增强方法");}
}

动态代理

看了静态代理之后,思考这样一个问题:当我们需要对许多对象进行相同的增强时,我们难道要手写很多个代理类来完成吗?

我们发现,只要我们知道一个被代理对象的所有方法及其参数和返回值,我们就可以让程序自动生成代理对象的字节码并加载到JVM中。这就是动态代理的思路。

在Spring中使用了两种动态代理方式来实现AOP,分别是jdk的动态代理和基于CGLib的代理。

jdk动态代理

jdk动态代理主要涉及到两个类:java.lang.reflect.InvocationHandler和 java.lang.reflect.Proxy

通过一个小例子来看一下如何使用jdk动态代理

public class MyHandler implements InvocationHandler {Object target;  public MyHandler(Object target) {this.target = target;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {Object result = method.invoke(target, args);return result;}
}
QueryrServiceImpl queryServiceImpl = new QueryServiceImpl();
//获取被代理对象的类加载器
ClassLoader classLoader = queryServiceImpl.getClass().getClassLoader();
//获取被代理对象实现的所有接口
Class[] interfaces = queryServiceImpl.getClass().getInterfaces();
InvocationHandler myHandler = new MyHandler(queryServiceImpl);
QueryService proxy = (QueryService) Proxy.newProxyInstance(classLoader, interfaces, myHandler);

从Proxy.newProxyInstance的interfaces参数我们可以得知,jdk动态代理是根据被代理对象实现的接口来判断需要代理哪些方法的,因此jdk动态代理要求被代理对象实现了接口。

CGLIB动态代理

CGLIB动态代理也涉及到两个类:MethodInterceptor和Enhancer

同样通过一个小例子看如何使用CGLIB动态代理

public class MyInterceptor implements MethodInterceptor {@Overridepublic Object intercept(Object object, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {Object result = methodProxy.invokeSuper(object, objects);return result;}}
Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(QueryServiceImpl.class);
enhancer.setCallback(new MyInterceptor());
QueryServiceImpl queryService = (QueryServiceImpl) enhancer.create();

CGLIB是使用了ASM机制生成被代理对象的子类并添加拦截方法。由于他是被代理对象的子类,因此他无法增强被final修饰的方法。

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

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

相关文章

Node.js 22 发布,原生支持 WebSocket 客户端

昨日,Node.js 官方博客正式宣布 Node.js 22 的发布!新版本亮点包括 require() ES 模块、WebSocket 客户端、V8 JavaScript 引擎的更新等! Node.js 22 将在 10 月进入长期支持 (LTS),但在此之前,它将是接下来六个月的 …

【AI相关】数学和统计学知识

数学和统计学的知识可以分为两部分: 一部分是线性代数中的基础概念,比如标量、向量和张量。 另一部分是概率统计中常见的分布类型,比如正态分布和伯努利分布。 线性代数 什么是标量? 标量是一个单独的数,可以是整…

PHP安装dbase扩展,2024最新安装日志,注意PHP版本、扩展目录路径、文件权限3个大坑

今天在我的免费云服务器,阿贝云上安装dbase扩展。系统是centos,安装好了宝塔面板。 第一步, yum install php-pear pecl install dbase (显示Installing ‘/usr/lib64/php/modules/dbase.so’ install ok: channel://pecl.php.net…

2021年全国大学生电子设计竞赛D题——基于互联网的摄像测量系统(二)

09 电路设计 前面介绍了系统的硬件框图如下: 硬件基本分为三块,两个摄像节点,一个终端节点。 1. 摄像节点硬件 摄像节点由一个DE10-Nano开发板和一个D8M摄像头实现,DE10-Nano开发板的HDMI接口外接HDMI显示器来显示拍摄到的视频。…

Linux:在线扩容

目录 项目场景 所需技术 操作步骤 Ⅰ:查看pv(物理卷)、vg(卷组)大小是否还够扩容 Ⅱ:vda磁盘新增分区vda3 Ⅲ:pv(逻辑卷)扩容 Ⅳ:vg(卷组&…

ABC350 FG 题解

ABC350 FG 题解 本人 Unrated 在开始后 1h 参加,20 分钟过 F,1h 过 G。 F Overview 唐,史上最水 F。 Description 有一个串 S S S,包含大小写字母,( 和 ),保证括号匹配。 对于每组匹配括号&#xf…

vue3的getCurrentInstance获取当前组件实例

vue3的setup中没有this时需要使用getCurrentInstance()来获取。 在 Vue 3 中,getCurrentInstance 方法可以在组合式 API(Composition API)中获取当前组件实例。这个方法返回一个包含了组件实例的对象,你可以用它来访问组件的 pro…

详解MySQL C API 相关接口(大白话就是:MySQL的c语言怎么写)

文章目录 1、C API 官方文档2、初始化 MYSQL3、连接 MySQL设置连接字符集(使得客户端编码方式匹配) 4、下发 mysql 指令5、获取 mysql 查询结果(保存起来)获取行与列遍历存储结果 6、释放 MYSQL\_RES 对象7、关闭 MySQL 连接8、总结 1、C API 官方文档 …

动态规划---斐波那契数列模型

目录 一、斐波那契数列的基本概念 二、动态规划在斐波那契数列中的应用与优势 三、实际案例:使用动态规划解决斐波那契数列问题 四、动态规划问题的做题步骤 五、例题 1、第N个泰波那契数---点击跳转题目 2、三步问题----点击跳转题目 3、最小花费爬楼梯---…

FANUC机器人socket通讯硬件配置

一、添加机器人选配包 Fanuc机器人要进行socket通讯,需要有机器人通讯的选配包,1A05B-2600-R648 User Socket Msg,1A05B-2600-R632 KAREL,1A05B-2600-R566 KAREL Diagnostic,1A05B-2600-J971 KAREL Use Sprt FCTN。 二…

【漏洞复现】WebLogic XMLDecoder反序列化(CVE-2017-10271)

1、漏洞描述 CVE-2017-10271漏洞产生的原因大致是Weblogic的WLS Security组件对外提供webservice服务,其中使用了XMLDecoder来解析用户传入的XML数据,在解析的过程中出现反序列化漏洞,导致可执行任意命令。攻击者发送精心构造的xml数据甚至能…

SpringMvc中的异常处理器(在SpringBoot中也可使用)

目录 一、单个控制器异常处理 二、全局异常处理器 三、自定义异常处理器 在开发过程中,Dao,service,Controller层代码出现异常都可能抛出异常。如果哪里产生异常就在哪里处理异常,则会降低开发效率。所以一般情况下我们会让异常…

clickhouse数据去重函数介绍(count distinct)

非精确去重函数:uniq、uniqHLL12、uniqCombined 精确去重函数:uniqExact、groupBitmap 测试数据量:2000w 结论: 1.整形值精确去重场景,groupBitmap 比 uniqExact至少快 2x 2.groupBitmap仅支持无符号整形值去重&#x…

文化旅游3D数字孪生可视化管理平台推动文旅产业迈向更加美好的未来

随着数字化、智能化管理成为文旅产业发展的必然趋势,数字孪生公司深圳华锐视点创新性地推出了景区三维可视化数字孪生平台,将线下的实体景区与线上的虚拟世界完美融合,引领智慧文旅新潮流。 我们运用先进的数字孪生、web3D开发和三维可视化等…

【Bug记录】@RequestBody参数属性为空的问题

1、问题发生背景 使用postman调用之前测试成功的接口,再进行项目拆分,重构之后,接口突然不通了,排查了很久,以为是框架调整,导致出了问题。 2、问题发生的原因 经过一系列的排查,排查详细过程就…

linux内核网络源码-用户空间与内核的接口

内核通过各种不同的接口把内部信息输出到用户空间,除了程序员用于请求特定信息的经典系统调用外,还有三个特殊接口,而其中两个是虚拟文件系统: procfs 文件系统 这是一个虚拟文件系统,通过是挂在proc ,允许内核以文件的…

详解Qt中的鼠标事件

在Qt中,处理鼠标事件是构建交互式界面的关键。Qt提供了一系列与鼠标相关的事件处理函数,允许开发者捕获鼠标的各种动作,如按下、释放、移动、双击等。以下是鼠标事件的使用方法、技巧以及注意事项,并附带C代码示例。 基础使用方法…

GDB多线程调试:Redis的IO多线程

Redis采用的网络模型是单线程的Reactor网络模型,异步处理,因为性能很高。 Reactor先从客户端获取请求,然后dispatch给具体的执行的线程。处理的流程即为read->decode->compute->encode->send。 而Redis的IO多线程的处理时&…

【C++】:拷贝构造函数和赋值运算符重载

目录 一,拷贝构造函数1. 什么是拷贝构造函数2. 拷贝构造函数的特性3. 实践总结 二,赋值运算符重载2.1 运算符重载2.2 赋值运算符重载 一,拷贝构造函数 1. 什么是拷贝构造函数 拷贝构造函数是特殊的构造函数。是用一个已经存在的对象&#x…

什么是哈希表

为了解力扣第一题自学哈希表,做总结。 哈希函数的原理: 如果输入一个参数,那么哈希函数就会输出一个数字,并且不同的输入会有不同的输出,相同的输入会有相同的输出。例如: 苹果————89 苹果————…