静态代理,jdk动态代理,cglib动态代理

文章目录

  • 静态代理
  • 动态代理
    • jdk动态代理
    • JDK生成的动态代理类大概源码
    • cglib动态代理

代理模式就是用代理对象代替真实对象去完成相应的操作,并且能够在操作执行的前后对操作进行增强处理。

静态代理

mybatis使用的就是静态代理,相比动态代理,静态代理在编译期间就确定了代理类,因此在运行时的性能通常会比动态代理更好。
步骤:定义接口,真实类实现接口,代理类也实现接口

真实场景,我们现在有一个歌手,歌手只想唱歌,不想管其他的事情,这时歌手就需要一个代理人,歌手代理人完成除唱歌之外的所有琐事,等完成了一系列工作后,再让歌手来唱歌。

定义业务接口

public interface Service {void sing();
}

真实类实现业务接口

public class Singer implements Service{public void sing() {System.out.println("歌手演唱");}
}

代理人实现业务接口

public class SingerProxy implements Service{public void sing() {System.out.println("歌手经纪人预定唱歌时间");System.out.println("歌手经纪人预定唱歌场地");System.out.println("歌手经纪人通知歌手唱歌");Singer singer = new Singer();singer.sing();System.out.println("歌手经纪人清理场地");}
}

调用代理人去让歌手完成唱歌

public class Main {public static void main(String[] args) {SingerProxy singerProxy = new SingerProxy();singerProxy.sing();}}

运行结果:
在这里插入图片描述

动态代理

静态代理的缺陷显而易见,每有一个真实类,我们就需要手动创建他的代理类,代码量巨大,这时我们的需求就是能不能动态生成。
动态代理是在程序运行时动态生成代理对象,而不是在编译时就确定代理对象。这意味着可以根据需要在运行时创建不同的代理对象,以满足不同的需求。

jdk动态代理

java.lang.reflect.Proxy类:提供了为对象产生代理对象的方法:

业务接口

public interface Service {void sing();void dance();
}

真实类实现业务接口

public class Singer implements Service{public void sing() {System.out.println("歌手演唱");}public void dance() {System.out.println("歌手跳舞");}}

生成代理类

public class Main {public static void main(String[] args) {//创建真实对象Singer singer = new Singer();//动态创建真实对象的被代理对象Service proxy = createProxy(singer);proxy.sing();}//生成代理类public static Service createProxy(Singer singer){Service proxy = (Service)Proxy.newProxyInstance(Singer.class.getClassLoader(),    //类的加载器new Class[]{Service.class},	    //接口数组new InvocationHandler() {       //调用处理器@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {				//proxy 代理对象,method正在执行的方法,agrs方法参数//先获取正在执行的方法名String name = method.getName();Object result = null;//if ("sing".equals(name)) {System.out.println("歌手经纪人预定唱歌时间");System.out.println("歌手经纪人预定唱歌场地");System.out.println("歌手经纪人通知歌手唱歌");result = method.invoke(singer, args);System.out.println("歌手经纪人清理场地");}if ("dance".equals(name)) {System.out.println("歌手经纪人预定跳舞时间");System.out.println("歌手经纪人预定跳舞场地");System.out.println("歌手经纪人通知歌手唱跳");result = method.invoke(singer, args);System.out.println("歌手经纪人清理场地");}return result;}});return proxy;}}

JDK生成的动态代理类大概源码

动态生成的代理类其方法与实现的接口有关,接口有什么方法,他就实现什么方法。

当我们代理类对象.sing()时,代理类内部会有sing方法,sing方法中会super.h.invoke(代理对象本身,正在执行的方法,方法参数)。super是其父类Proxy,h是父类的属性InvocationHandler h,这个调用处理器是我们传给父类对象的。
当我们代理类对象.dance()时,代理类内部会有dance方法,dance方法同样有super.h.invoke(代理对象本身,正在执行的方法,方法参数)。super是其父类Proxy,h是父类的属性InvocationHandler h,这个调用处理器是我们传给父类对象的。

public final class $Proxy0 extends Proxy implements Service {private static Method m0;private static Method m1;private static Method m2;private static Method m3;private static Method m4;public $Proxy0(InvocationHandler var1) throws  {super(var1);}public final boolean equals(Object var1) throws  {try {return (Boolean)super.h.invoke(this, m0, new Object[]{var1});} catch (RuntimeException | Error var3) {throw var3;} catch (Throwable var4) {throw new UndeclaredThrowableException(var4);}}public final String toString() throws  {try {return (String)super.h.invoke(this, m1, (Object[])null);} catch (RuntimeException | Error var2) {throw var2;} catch (Throwable var3) {throw new UndeclaredThrowableException(var3);}}public final int hashCode() throws  {try {return (Integer)super.h.invoke(this, m2, (Object[])null);} catch (RuntimeException | Error var2) {throw var2;} catch (Throwable var3) {throw new UndeclaredThrowableException(var3);}}//Method m3中有sing方法的信息,调用父类Proxy的protected InvocationHandler h 的invoke方法public final void sing() throws  {try {super.h.invoke(this, m3, (Object[])null);} catch (RuntimeException | Error var2) {throw var2;} catch (Throwable var3) {throw new UndeclaredThrowableException(var3);}}//Method m4中有dance方法的信息public final void dance() throws  {try {super.h.invoke(this, m4, (Object[])null);} catch (RuntimeException | Error var2) {throw var2;} catch (Throwable var3) {throw new UndeclaredThrowableException(var3);}}static {try {m0 = Class.forName("java.lang.Object").getMethod("equals", Class.forName("java.lang.Object"));m1 = Class.forName("java.lang.Object").getMethod("toString");m2 = Class.forName("java.lang.Object").getMethod("hashCode");m3 = Class.forName("Service").getMethod("sing");m4 = Class.forName("Service").getMethod("dance");} catch (NoSuchMethodException var2) {throw new NoSuchMethodError(var2.getMessage());} catch (ClassNotFoundException var3) {throw new NoClassDefFoundError(var3.getMessage());}}
}

cglib动态代理

jdk动态代理需要接口,许多场景是没有接口的,这个时候就需要cglib动态代理了,CGLIB(Code Generation Library)是一个基于ASM的字节码生成库,它允许我们在运行时对字节码进行修改和动态生成。CGLIB通过继承方式实现代理。

cglib代理最重要的是实现MethodInterceptor接口,实现他的intercept方法
jdk代理最重要的是实现 InvocationHandler接口,实现他的invoke方法

当我们代理类对象.sing() --> MethodInterceptor. intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) -->根据类名通过反射调用对应的方法

intercept方法的四个参数
Object o, 被代理对象
Method method, 正在执行的方法
Object[] objects, 方法参数
MethodProxy methodProxy 方法代理对象

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

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

相关文章

Mamba: Linear-Time Sequence Modeling with Selective State Spaces(论文笔记)

What can I say? 2024年我还能说什么? Mamba out! 曼巴出来了! 原文链接: [2312.00752] Mamba: Linear-Time Sequence Modeling with Selective State Spaces (arxiv.org) 原文笔记: What: Mamba: Linear-Time …

STL的基本概念

一、STL的诞生 长久以来,软件界一直希望建立一种可重复利用的东西 C的面向对象和泛型编程思想,目的就是复用性的提升 面向对象的三大特性(简单理解) 封装:把属性和行为抽象出来作为一个整体来实现事和物 继承:子类继承父类&a…

Gui guider使用自定义字体总结

在实际开发中,我们通常是使用自定义字体。 在 LVGL 中,用户需要使用自定义的字库,其实现方法可分为两类: ① 通过 C 语言数组(内部读取); ② 通过文件系统读取字库(外部读取&#…

【CAD建模号小技巧】边缘尖角光滑处理方法

教大家一个处理模型边缘的方法,处理后模型更美观,更不易坏,而且有些零件还必须经过这样的处理。 咱们看一个未经过边缘处理的模型,边缘是尖的,摸到会刺伤,一些接近刀口形状。 更危险了,所以要进…

javascript基础代码练习

一、输入新增病例数&#xff0c;累计确诊病例数&#xff0c;14天内聚集性疫情发生天数。新增或者累计确诊病例为0则该地区为低风险地区。新增大于0且累计确诊&#xff1c;50或者累计大于50且14天内聚集性疫情发生天数为0的地区为中风险地区。其他情况为高风险地区。 <!DOCT…

大数据开发(离线实时音乐数仓)

大数据开发&#xff08;离线实时音乐数仓&#xff09; 一、数据库与ER建模1、数据库三范式2、ER实体关系模型 二、数据仓库与维度建模1、数据仓库&#xff08;Data Warehouse、DW、DWH&#xff09;1、关系型数据库很难将这些数据转换成企业真正需要的决策信息&#xff0c;原因如…

C语言程序练习——汉诺塔递归

1. 题目 在终端输入汉诺塔层数n&#xff0c;实现将n层汉诺塔通过三座塔座A、B、C进行排列 2. 代码 #include <stdio.h>int hannuota(int len, int str, int tmp, int dst) {if (1 len){printf("%c -> %c\n", str, dst);}else{hannuota(len-1, str, dst, …

Python更改Word文档的页面大小

页面大小确定文档中每个页面的尺寸和布局。在某些情况下&#xff0c;您可能需要自定义页面大小以满足特定要求。在这种情况下&#xff0c;Python可以帮助您。通过利用Python&#xff0c;您可以自动化更改Word文档中页面大小的过程&#xff0c;节省时间和精力。本文将介绍如何使…

Python---Numpy学习

首先&#xff0c;先来认识一下Numpy数组对象&#xff0c;以及如何创建它 import numpy as np# 1.认识数组对象 # 指定取值范围和跨度创建数组对象 # 创建一个3行4列的数组 data np.arange(12).reshape(3, 4)print(data)print(type(data))# 维度 print(data.shape)# 维度的个数…

【Java程序设计】【C00364】基于Springboot的美发管理系统(有论文)

基于Springboot的美发管理系统&#xff08;有论文&#xff09; 项目简介项目获取开发环境项目技术运行截图 项目简介 项目获取 &#x1f345;文末点击卡片获取源码&#x1f345; 开发环境 运行环境&#xff1a;推荐jdk1.8&#xff1b; 开发工具&#xff1a;eclipse以及idea&…

「媒体宣传」如何针对不同行业制定媒体邀约方案

传媒如春雨&#xff0c;润物细无声&#xff0c;大家好&#xff0c;我是51媒体网胡老师。 针对不同行业制定媒体邀约方案时&#xff0c;需要考虑行业特点、目标受众、媒体偏好以及市场趋势等因素。 一、懂行业 先弄清楚你的行业是啥样&#xff0c;有啥特别之处。 了解行业的热…

鸿蒙OS应用示例:【数字滚动计时】

实现效果&#xff1a; 代码示例&#xff1a; RollingText.ets 组件封装 RollingText.ets 组件封装 /*** 滚动文字特效*/ Component export default struct RollingText {private num:numberprivate timerId: number -1State counter: number 0aboutToAppear() {this.timerId…