当前位置: 首页 > news >正文

Java三种代理模式:静态代理、动态代理和CGLIB代理

Java三种代理模式:静态代理、动态代理和CGLIB代理

代理模式

代理模式是23种设计模式种的一种。代理模式是一种结构型设计模式,它允许为其他对象提供一个替代品或占位符,以控制对这个对象的访问。代理模式可以在不修改被代理对象的基础上,通过扩展代理类,进行一些功能的附加与增强。

代理模式的构成

适配器模式一般包含三种角色:

  • 抽象主题角色(Subject):通过接口或抽象类声明真实角色实现的业务方法。
  • 代理主题角色(Proxy):实现抽象角色,是真实角色的代理(访问层),通过真实角色的业务逻辑方法来实现抽象方法,并可以附加自己的操作。
  • 真实主题角色(RealSubject):实现抽象角色,定义真实角色所要实现的业务逻辑,供代理角色调用。

代理模式主要有三种形式,分别是静态代理、动态代理(也称JDK代理、接口代理)和CGLIB代理(在内存动态创建对象而不需要实现接口,也可属于动态代理得范畴)

静态代理

静态代理是定义父类或者接口,然后被代理对象(即目标对象)与代理对象一起实现相同的接口或者是继承相同父类。代理对象与目标对象实现相同的接口,然后通过调用相同的方法来调用目标对象的方法。

  • 优点:可不修改目标对象的功能,通过代理对象对目标功能扩展。
  • 缺点:因为代理对象需要与目标对象实现一样的接口,所以会有很多代理类,一旦接口增加方法,目标对象与代理对象都要维护。
public interface Animal {void eat();
}
public class Dog implements Animal {@Overridepublic void eat() {System.out.println("吃吃吃");}
}
public class DogProxy implements Animal {private Animal target; //通过接口聚合目标对象public DogProxy(Animal target) {this.target = target;}@Overridepublic void eat() {System.out.println("静态代理开始");target.eat();System.out.println("静态代理结束");}
}
public class Main {public static void main(String[] args) {//创建被代理对象Dog dog = new Dog();//创建代理对象, 同时将被代理对象传递给代理对象DogProxy dogProxy = new DogProxy(dog);//通过代理对象,调用到被代理对象的方法dogProxy.eat();}
}

image-20231128203835440

动态代理

动态代理是在运行时动态生成代理类,不需要手动编写代理类。Java种的动态代理主要是使用java.lang.reflect.Proxy和java.lang.reflect.InvocationHandler接口实现。

优点:灵活性高、减少重复代码、统一处理逻辑、可以代理多个真实类。
缺点:基于反射机制,性能较低,且无法代理final类和方法。

动态代理最主要的就是Proxy.newProxyInstance方法,它是用于创建动态代理对象的静态方法。它接受三个参数:

ClassLoader:用于加载动态代理类的类加载器。
interfaces:要代理的接口数组。
InvocationHandler:实现了InvocationHandler接口的对象,用于处理代理对象的方法调用。

public interface Animal {void eat();
}
public class Dog implements Animal {@Overridepublic void eat() {System.out.println("吃吃吃");}
}
public class AnimalInvocationHandler implements InvocationHandler {private Object target;public AnimalInvocationHandler(Object target) {this.target = target;}@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("吃前加热");Object result = method.invoke(target, args);System.out.println("吃后清理");return result;}
}
public class AnimalProxy {public static Animal createProxy(Animal animal) {return (Animal) Proxy.newProxyInstance(animal.getClass().getClassLoader(),animal.getClass().getInterfaces(),new AnimalInvocationHandler(animal));}
}
public class Main {public static void main(String[] args) {Dog dog = new Dog();Animal dogProxy = AnimalProxy.createProxy(dog);dogProxy.eat();}
}

image-20231128205554639

JDK 动态代理有一个最致命的问题是其只能代理实现了接口的类。

为了解决这个问题,我们可以用 CGLIB 动态代理机制来避免。

CGLIB代理

CGLIB代理也叫作子类代理,它使目标对象不需要实现接口,是在内存中构建一个子类对象从而实现对目标对象功能扩展,有的也将CGLIB代理归属到动态代理。

CGLIB是一个高性能的代码生成包,它可以在运行期扩展java类与实现java接口。被许多AOP的框架使用(如Spring AOP)。Cglib包的底层是通过使用字节码处理框架ASM来转换字节码并生成新的类。

  • 优点:可以为没有实现接口的类提供代理;性能比动态代理更高
  • 缺点:生成的代理类较大、不支持final方法和类、对于final类和方法的处理相对复杂。
public class Dog {public void eat() {System.out.println("吃吃吃");}
}
public class AnimalMethodInterceptor implements MethodInterceptor {@Overridepublic Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {System.out.println("吃前加热");Object result = methodProxy.invokeSuper(o, objects);System.out.println("吃后清理");return result;}
}
public class DogCglibProxy {public static Dog createProxy() {Enhancer enhancer = new Enhancer();enhancer.setSuperclass(Dog.class);enhancer.setCallback(new AnimalMethodInterceptor());return (Dog) enhancer.create();}
}
public class Main {public static void main(String[] args) {Dog dogProxy = DogCglibProxy.createProxy();dogProxy.eat();}
}

image-20231128211037905

CGLIB与java动态代理的区别

  1. 实现方式:
    • Java动态代理:使用java.lang.reflect.ProxyInvocationHandler接口。Java动态代理只能为接口创建代理对象,它是基于接口的代理。通过Proxy.newProxyInstance()方法可以动态地生成实现了指定接口的代理类。
    • CGLIB:通过继承目标类的方式创建代理对象。CGLIB可以为类创建代理,而不仅仅是接口。它通过生成目标类的子类,在子类中增加代理逻辑来实现动态代理。
  2. 代理对象类型:
    • Java动态代理:只能代理实现了接口的类。它要求目标对象实现一个或多个接口,然后通过代理对象来实现这些接口。
    • CGLIB:可以代理没有实现任何接口的类。它通过继承目标类来创建代理对象,因此目标类不需要实现任何接口。
  3. 性能:
    • Java动态代理:由于生成的代理对象是基于接口的,因此在调用代理方法时,会通过接口的方法调用InvocationHandlerinvoke方法,再由invoke方法调用实际的目标方法。这一层额外的调用可能会引入一些性能开销。
    • CGLIB:生成的代理对象是目标类的子类,因此调用代理方法时,直接调用子类中的方法,避免了通过接口的中间层,可能会在一些情况下具有更好的性能。
  4. 构造方式:
    • Java动态代理:通过Proxy.newProxyInstance()方法动态生成代理对象,需要提供一个实现InvocationHandler接口的对象。
    • CGLIB:通过CGLIB库动态生成代理对象,无需提供InvocationHandler。CGLIB通过继承目标类并重写其中的方法来实现代理逻辑。

应用场景

代理模式可以在多种场景下使用,包括但不限于以下几个方面:

  1. 访问控制:代理模式可以用来控制对实际对象的访问权限。比如,只有特定用户或角色才能访问某些敏感数据。
  2. 远程访问:代理模式可以用来处理远程对象的访问。比如,通过代理对象来访问远程Web服务。
  3. 延迟加载:代理模式可以用来实现延迟加载。比如,通过代理对象来加载某些资源或数据,以避免在程序启动时就加载所有数据。
  4. 虚拟代理:当需要延迟加载或预加载大量数据时,可以使用虚拟代理来提高程序的性能和效率。

应用场景

代理模式可以在多种场景下使用,包括但不限于以下几个方面:

  1. 访问控制:代理模式可以用来控制对实际对象的访问权限。比如,只有特定用户或角色才能访问某些敏感数据。
  2. 远程访问:代理模式可以用来处理远程对象的访问。比如,通过代理对象来访问远程Web服务。
  3. 延迟加载:代理模式可以用来实现延迟加载。比如,通过代理对象来加载某些资源或数据,以避免在程序启动时就加载所有数据。
  4. 虚拟代理:当需要延迟加载或预加载大量数据时,可以使用虚拟代理来提高程序的性能和效率。
  5. 缓存代理:当需要对经常使用的数据进行缓存时,可以使用缓存代理来管理和优化数据的访问效率。

相关文章:

Java三种代理模式:静态代理、动态代理和CGLIB代理

Java三种代理模式:静态代理、动态代理和CGLIB代理 代理模式 代理模式是23种设计模式种的一种。代理模式是一种结构型设计模式,它允许为其他对象提供一个替代品或占位符,以控制对这个对象的访问。代理模式可以在不修改被代理对象的基础上&am…...

vivado实现分析与收敛技巧9-分析使用率统计数据

实现问题的常见原因之一是未考量显式和隐式物理约束。例如 , 管脚分配 (pinout) 在逻辑布局上变为显式物理约束。 slice( 分片 ) 逻辑在大部分器件中都是一致的。但如下专用资源表示的是隐式物理约束 , 因为这些资源仅在某些位置…...

7nm项目之顶层规划——01数据导入

1.创建workspace 创建workspace后,在其目录下产生。 CORTEXA53.json文件是将有默认配置的文件master.json、有library的.config.json文件、tunes下CORTEXA53.tunes.json文件合并 注:tunes下的CORTEXA53.tunes.json文件可以覆盖一些master.json的设置…...

一键式紧急报警柱系统

随着科技的不断发展,一键式紧急报警柱在我们的生活和工作中扮演着越来越重要的角色。在这篇文章中,我们将一起探究与一键式紧急报警柱有关的知识。 一键式紧急报警柱是一种常见的安全防护设备,能够在紧急情况下快速发出警报,保护…...

4-Docker命令之docker run

1.docker run介绍 docker run命令是用来创建新的容器并运行相关命令 2.docker run用法 docker run [参数] [root@centos79 ~]# docker run --helpUsage: docker run [OPTIONS] IMAGE [COMMAND] [ARG...]Create and run a new container from an imageAliases:docker conta…...

【模电】直流通路与交流通路

直流通路与交流通路 通常,在放大电路中,直流电源的作用和交流信号的作用总是共存的,即静态电流、电压和动态电流、电压总是共存的。但是由于电容、电感等电抗元件的存在,直流量所流经的通路与交流信号所流经的通路不完全相同。因此…...

SpringBoot JprotoBuf序列化与反序列化的实现

文章目录 前言一、protobuf与JprotoBufprotobuf介绍JprotoBuf介绍protobuf与JprotoBuf的区别二、JprotoBuf特点三、类型转换对照表四、ProtobufClass编写五、序列化与反序列化测试六、使用JprotoBuf时的注意事项七、JprotoBuf与protobuf序列化反序列化结果比较前言 在软件开发…...

互联网Java工程师面试题·Spring Boot篇·第一弹

目录 1、什么是 Spring Boot? 2、Spring Boot 有哪些优点? 3、什么是 JavaConfig? 4、如何重新加载 Spring Boot 上的更改,而无需重新启动服务器? 5、Spring Boot 中的监视器是什么? 6、如何在 Sprin…...

HostHunter虚拟主机发现

HostHunter虚拟主机发现 1.HostHunter2.安装3.参数解释4.实例1.HostHunter HostHunter 一种工具,用于有效发现和提取提供大量目标 IPv4 或 IPv6 地址的主机名。HostHunter 利用简单的 OSINT 和主动协调技术将 IP 目标与虚拟主机名进行映射。这对于发现组织的真正攻击面特别有…...

鸿蒙开发:UIAbility组件间交互探索实战【鸿蒙专栏-22】

UIAbility组件间交互(设备内) 在设备内,UIAbility(用户界面能力)是系统调度的最小单元,它们负责展示用户界面和执行相关的业务逻辑。设备内的不同功能模块之间的交互是应用程序开发中的重要部分。本文将探讨设备内UIAbility之间的交互方式,包括启动应用内的UIAbility、…...

VSCode Vue 开发环境配置

Vue是前端开发中的重要工具与框架,可以保住开发者高效构建用户界面。 Vue2官方文档:https://v2.cn.vuejs.org/ Vue3官方文档:https://cn.vuejs.org/ Vue的安装和引用 Vue2的官方安装指南:https://v2.cn.vuejs.org/v2/guide/ins…...

clickhouse从mysql同步数据到clickhouse的几种方式

背景 我们的业务数据一般来说都是放在Mysql中的,而我们要分析的数据一般都存放在clickhouse中,所以如何把数据从mysql同步到ck,就变成了一个必须的步骤,本文简单记录下几种同步的方式 mysql数据同步到clickhouse 方式一&#x…...

“滑动窗口”算法实例

1 问题 给定一个字符串“S”,找出其中不含有重复字符的最长子串的长度。例如:S‘ABCABCBB’,则不含重复字符的最长字串长度为3.。S‘ABCDFG’,则不含重复字符的最长字串长度为6。要求设计一个Python程序实现该功能? 2 方法 按照一…...

分布式搜索引擎elasticsearch(一)

5.1 初始elasticsearch elasticsearch是一款非常强大的开源搜索引擎,可以帮助我们从海量数据中快速找到需要的内容。 elasticsearch是elastic stack的核心,负责存储、搜索、分析数据。 5.1.1正向索引 5.1.2elasticsearch采用倒排索引: 文档(document):每条数据就是一个…...

PTA 7-236 验证哥德巴赫猜想

哥德巴赫猜想之一是指一个偶数(2除外)可以拆分为两个素数之和。请验证这个猜想。 因为同一个偶数可能可以拆分为不同的素数对之和,这里要求结果素数对彼此最接近。 输入格式: 首先输入一个正整数T,表示测试数据的组数&#xff0…...

微信小程序 纯css画仪表盘

刚看到设计稿的时候第一时间想到的就是用canvas来做这个仪表盘&#xff0c;虽然本人的画布用的不是很好但还可以写一写&#x1f600;。话不多说直接上代码。最后有纯css方法 <!--wxml--> <canvas canvas-id"circle" class"circle" >// js dat…...

成为AI产品经理——模型稳定性评估(PSI)

一、PSI作用 稳定性是指模型性能的稳定程度。 上线前需要进行模型的稳定性评估&#xff0c;是否达到上线标准。 上线后需要进行模型的稳定性的观测&#xff0c;判断模型是否需要迭代。 稳定度指标(population stability index ,PSI)。通过PSI指标&#xff0c;我们可以获得不…...

操作系统——进程同步

目录 一、信号量相关函数 1. 创建信号量集 2. 获取信号量集 3. 等待、通知信号量集 4. 控制信号量集 二、简单进程同步 1. 创建信号量集 2. P操作 3. V操作 4. 删除信号量集 5. 测试&#xff1a; 三、生产者与消费者 1. 创建、删除共享内存及信号量集 2. 单一生产…...

如何能够对使用ShaderGraph开发的Shader使用SetTextureOffset和SetTextureScale方法

假设在ShaderGraph中的纹理的引用名称为"_BaseMap"&#xff0c;同时对这个"_BaseMap"纹理使用了采样的节点"SampleTexture2D"&#xff0c;然后该采样节点的uv接入的TilingAndOffset节点&#xff0c;此时的关键步骤是新建一个Vector4属性&#xf…...

力扣572:另一棵树的子树

力扣572&#xff1a;另一棵树的子树 给你两棵二叉树 root 和 subRoot 。检验 root 中是否包含和 subRoot 具有相同结构和节点值的子树。如果存在&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 二叉树 tree 的一棵子树包括 tree 的某个节点和这个节点的所…...

.Net框架,除了EF还有很多很多......

文章目录 1. 引言2. Dapper2.1 概述与设计原理2.2 核心功能与代码示例基本查询多映射查询存储过程调用 2.3 性能优化原理2.4 适用场景 3. NHibernate3.1 概述与架构设计3.2 映射配置示例Fluent映射XML映射 3.3 查询示例HQL查询Criteria APILINQ提供程序 3.4 高级特性3.5 适用场…...

Linux简单的操作

ls ls 查看当前目录 ll 查看详细内容 ls -a 查看所有的内容 ls --help 查看方法文档 pwd pwd 查看当前路径 cd cd 转路径 cd .. 转上一级路径 cd 名 转换路径 …...

【ROS】Nav2源码之nav2_behavior_tree-行为树节点列表

1、行为树节点分类 在 Nav2(Navigation2)的行为树框架中,行为树节点插件按照功能分为 Action(动作节点)、Condition(条件节点)、Control(控制节点) 和 Decorator(装饰节点) 四类。 1.1 动作节点 Action 执行具体的机器人操作或任务,直接与硬件、传感器或外部系统…...

【服务器压力测试】本地PC电脑作为服务器运行时出现卡顿和资源紧张(Windows/Linux)

要让本地PC电脑作为服务器运行时出现卡顿和资源紧张的情况&#xff0c;可以通过以下几种方式模拟或触发&#xff1a; 1. 增加CPU负载 运行大量计算密集型任务&#xff0c;例如&#xff1a; 使用多线程循环执行复杂计算&#xff08;如数学运算、加密解密等&#xff09;。运行图…...

鱼香ros docker配置镜像报错:https://registry-1.docker.io/v2/

使用鱼香ros一件安装docker时的https://registry-1.docker.io/v2/问题 一键安装指令 wget http://fishros.com/install -O fishros && . fishros出现问题&#xff1a;docker pull 失败 网络不同&#xff0c;需要使用镜像源 按照如下步骤操作 sudo vi /etc/docker/dae…...

uniapp中使用aixos 报错

问题&#xff1a; 在uniapp中使用aixos&#xff0c;运行后报如下错误&#xff1a; AxiosError: There is no suitable adapter to dispatch the request since : - adapter xhr is not supported by the environment - adapter http is not available in the build 解决方案&…...

使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台

🎯 使用 Streamlit 构建支持主流大模型与 Ollama 的轻量级统一平台 📌 项目背景 随着大语言模型(LLM)的广泛应用,开发者常面临多个挑战: 各大模型(OpenAI、Claude、Gemini、Ollama)接口风格不统一;缺乏一个统一平台进行模型调用与测试;本地模型 Ollama 的集成与前…...

【分享】推荐一些办公小工具

1、PDF 在线转换 https://smallpdf.com/cn/pdf-tools 推荐理由&#xff1a;大部分的转换软件需要收费&#xff0c;要么功能不齐全&#xff0c;而开会员又用不了几次浪费钱&#xff0c;借用别人的又不安全。 这个网站它不需要登录或下载安装。而且提供的免费功能就能满足日常…...

C++:多态机制详解

目录 一. 多态的概念 1.静态多态&#xff08;编译时多态&#xff09; 二.动态多态的定义及实现 1.多态的构成条件 2.虚函数 3.虚函数的重写/覆盖 4.虚函数重写的一些其他问题 1&#xff09;.协变 2&#xff09;.析构函数的重写 5.override 和 final关键字 1&#…...

20个超级好用的 CSS 动画库

分享 20 个最佳 CSS 动画库。 它们中的大多数将生成纯 CSS 代码&#xff0c;而不需要任何外部库。 1.Animate.css 一个开箱即用型的跨浏览器动画库&#xff0c;可供你在项目中使用。 2.Magic Animations CSS3 一组简单的动画&#xff0c;可以包含在你的网页或应用项目中。 3.An…...