news 2026/8/18 12:24:29

结构型模式-代理模式

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
结构型模式-代理模式

本文介绍了代理模式,其他常见设计模式在本系列其他文章,有兴趣可了解

文章目录

  • 代理模式
    • 静态代理
    • 动态代理
    • **JDK动态代理**
    • **CGLIB代理**
  • 总结

代理模式

静态代理

举一个音乐会买票的例子感受一下静态代理:

定义一个售卖接口

publicinterfaceSell{publicvoidsell();}

定义音乐会售票类

publicclassConcertSellimplementsSell{@Overridepublicvoidsell(){System.out.println("卖票");}}

定义中介类
Java有自带的Proxy类,最好不要使用Proxy作为类名,在动态代理中我们会用到这个类
中介增强了ConcertSell的功能

publicclassProxyPointimplementsSell{privateConcertSellconcertSell=newConcertSell();@Overridepublicvoidsell(){System.out.println("中介收取费用");concertSell.sell();}}

运行

publicclassClient{publicstaticvoidmain(String[]args){ProxyPointproxy=newProxyPoint();proxy.sell();}}

结果

中介收取费用 卖票

这里使用了接口(使用接口比使用抽象父类耦合度低),音乐会售票类和中介类都继承这个接口,他们必须实现接口中的抽象方法(中介类在实现的方法中使用了音乐会售票类的方法),中介类在不影响音乐会售票类的同时增强了其功能

动态代理

JDK动态代理

JDK动态代理只能代理接口中定义的方法,换句话说目标类有接口才能用JDK动态代理
JDK动态代理不是代理了目标类(ConcertSell)而是通过反射使用了目标类实例对象的方法

准备好接口和目标类

接口

publicinterfaceSell{publicvoidsell();publicvoidsell2();}

目标类

publicclassConcertSellimplementsSell{@Overridepublicvoidsell(){System.out.println("卖场次1票");}@Overridepublicvoidsell2(){System.out.println("卖场次2票");}}

我们直接使用工厂模式建一个ProxyFactory工厂,将细节封装到这个工厂类中,通过一个getProxy()方法得到代理对象

publicclassProxyFactory{privateConcertSellconcertSell=newConcertSell();/*执行newProxyInstance()方法时,Java底层在内存中动态生成$Proxy0.class字节码, 必须通过类加载器加载到JVM内存中,才能成为一个可用的代理类, newProxyInstance()方法返回的是这个代理类的实例对象,并由 proxy 变量接收。 *//*newProxyInstance()方法有三个参数, 第一个参数是获取一个类加载器,用来加载$Proxy0.class到JVM内存中, 第二个参数是获取目标类实现的接口数组(这就是JDK动态代理只能代理接口中定义的方法的原因), 第三个参数是匿名内部类形式,其中有一个invoke方法(这里涉及到了反射),invoke方法三个参数分别是: Object proxy(代理对象自身), Method method(外部调用的接口方法), Object[] args(调用时传入的参数数组), method.invoke()利用了反射(这里的invoke方法和匿名内部类的invoke方法意义不同),调用了目标类实例对象的方法, 在invoke方法里可以对目标类实例对象方法进行增强 */publicSellgetProxy(){//JDK动态代理代理的是接口中的方法,强转类型自然是接口类型Sellproxy=(Sell)Proxy.newProxyInstance(concertSell.getClass().getClassLoader(),concertSell.getClass().getInterfaces(),newInvocationHandler(){@OverridepublicObjectinvoke(Objectproxy,Methodmethod,Object[]args)throwsThrowable{//方法体System.out.println("中介收取费用");method.invoke(concertSell,args);returnnull;}});returnproxy;}}

运行

publicclassClient{publicstaticvoidmain(String[]args){ProxyFactoryfactory=newProxyFactory();Sellproxy=factory.getProxy();proxy.sell();proxy.sell2();}}

结果

中介收取费用 卖场次1票 中介收取费用 卖场次2

CGLIB代理

CGLIB代理可以为没有实现接口的类提供代理
CGLIB代理类是目标类的子类(要求目标类可继承,因此CGLIB代理不能代理final修饰的类)
CGLIB代理是第三方提供的包,需引入对应jar包,maven工程中可引入jar包坐标(放在标签里)

<dependency><groupId>cglib</groupId><artifactId>cglib</artifactId><version>3.3.0</version></dependency>

jdk17报错可以将以上依赖替换为

<dependency><groupId>org.springframework</groupId><artifactId>spring-core</artifactId><version>6.1.8</version></dependency>

同时包名也要替换

// 原来是// import net.sf.cglib.proxy.Enhancer;// 现在改为importorg.springframework.cglib.proxy.Enhancer;

其他包名同理,将net.sf改为org.springframework
报错原因有兴趣可自行搜索

准备目标类ConcertSell

publicclassConcertSell{publicvoidsell(){System.out.println("卖场次1票");}publicvoidsell2(){System.out.println("卖场次2票");}}

我们同样使用工厂模式建一个ProxyFactory工厂,将细节封装到这个工厂类中,通过一个getProxy()方法得到代理对象

publicclassProxyFactory<T>implementsMethodInterceptor{privatefinalClass<T>targetClass;//创建ProxyFactory对象时,将目标类字节码传递过来,使ProxyFactory工厂成为一个通用工厂publicProxyFactory(Class<T>targetClass){this.targetClass=targetClass;}publicTgetProxy(){//创建工具类对象Enhancerenhancer=newEnhancer();//告诉CGLIB要生成的代理类,必须继承T(传过来的类型)enhancer.setSuperclass(targetClass);//设置回调函数,当代理对象的方法被调用时,会回调当前类的intercept方法//这里的参数要求必须是Callback接口的子类。而MethodInterceptor正是Callback最重要的子接口enhancer.setCallback(this);//返回代理对象,并强转成目标类类型return(T)enhancer.create();}@OverridepublicObjectintercept(Objecto,Methodmethod,Object[]objects,MethodProxymethodProxy)throwsThrowable{System.out.println("CGLIB中介收取费用");//可以使用method.invoke(o, objects),但这样就是利用反射调用方法了,效率低//CGLIB的优势,不是通过传统反射来调用父类方法,而是通过动态生成的字节码直接调用(类似invokevirtual指令),性能远高于JDK原生反射Objectresult=methodProxy.invokeSuper(o,objects);returnresult;}}

运行

publicclassClient{publicstaticvoidmain(String[]args){ProxyFactory<ConcertSell>proxyFactory=newProxyFactory(ConcertSell.class);ConcertSellproxy=proxyFactory.getProxy();//代理对象的方法被调用时,会回调intercept方法proxy.sell();proxy.sell2();}}

结果

CGLIB中介收取费用 卖场次1CGLIB中介收取费用 卖场次2

总结

以上就是本期要讲的内容,本文介绍了代理模式,其他常见设计模式在本系列其他文章,有兴趣可了解

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/18 12:23:46

多智能体协同架构在自适应网络安全故障排查中的设计与实践

1. 项目概述&#xff1a;当安全运维遇上智能体协同 最近在安全圈里&#xff0c;一个概念被讨论得越来越热&#xff1a;Multi-Agent&#xff08;多智能体&#xff09;。这不再是实验室里的玩具&#xff0c;而是开始真正落地到像安全事件响应、故障排查这类高压、复杂的实战场景中…

作者头像 李华
网站建设 2026/8/18 12:23:19

XMC1300 POSIF模块详解:三大传感器接口与速度捕获实战

1. 从“POSIF”这个外设说起&#xff1a;它到底是个啥&#xff1f;在嵌入式开发里&#xff0c;尤其是涉及到电机控制、编码器读取这类需要精确捕捉位置和速度的场景&#xff0c;我们经常会听到“定时器”这个词。但英飞凌XMC1000系列&#xff0c;特别是XMC1300&#xff0c;提供…

作者头像 李华
网站建设 2026/8/18 12:22:57

税务预警。

济南三千税务师事务所有限公司&#xff08;以下简称&#xff1a;济南三千财税&#xff09; 济南三千财税是专注于企业财税风险管控与合规体系建设的专业税务服务机构&#xff0c;始终秉持 “预警先行、合规为本、护航发展” 的服务理念&#xff0c;深耕本土企业财税服务场景&am…

作者头像 李华
网站建设 2026/8/18 12:22:45

c++对象模型--多态,运行时类型识别

虚函数机制 单一继承 单一继承下&#xff0c;类型包含虚函数时&#xff0c;每个class有一个virtual table&#xff0c;内含该class中有作用的virtual function的地址&#xff0c;然后每个class object有一个vptr&#xff0c;执向virtual table所在。 Point: Point2d: Poin…

作者头像 李华
网站建设 2026/8/18 12:21:22

Unity Mod Manager 使用教程:给 Unity 游戏装模组,看这一篇就够了

Unity Mod Manager 使用教程&#xff1a;给 Unity 游戏装模组&#xff0c;看这一篇就够了 【免费下载链接】unity-mod-manager UnityModManager 项目地址: https://gitcode.com/gh_mirrors/un/unity-mod-manager 你是不是也遇到过这样的尴尬&#xff1a;好不容易找到一个…

作者头像 李华