2026/5/14 3:05:57
网站建设
项目流程
seo推广介绍,怎么快速优化网站排名,企业网站模板,四川建设厅网站查询什么是代理模式#xff1f;生活化的比喻核心角色为什么要使用代理模式#xff1f;代理模式在Java中的实现静态代理动态代理静态代理与动态代理的区别实际应用场景什么是代理模式#xff1f;
代理模式#xff08;Proxy Pattern#xff09;是一种结构型设计模式#xff0c…什么是代理模式生活化的比喻核心角色为什么要使用代理模式代理模式在Java中的实现静态代理动态代理静态代理与动态代理的区别实际应用场景什么是代理模式代理模式Proxy Pattern是一种结构型设计模式它通过创建一个代理对象来控制对原始对象的访问。这种模式的核心思想是为其他对象提供一种代理以控制对这个对象的访问。生活化的比喻你可以把它想象成生活中的明星经纪人系统粉丝客户端 Client不能直接联系到明星真实对象 RealSubject需要通过经纪人代理 Proxy来与明星沟通经纪人可以帮明星处理很多事情过滤掉不重要的请求访问控制安排日程资源调度谈合同预处理/后处理明星本人则可以专注于自己的核心工作——表演业务逻辑在这个过程中经纪人和明星都实现了相同的能力接口比如接受采访、商业演出等所以对外界来说与经纪人沟通和与明星直接沟通在接口上是一致的但实际执行时经纪人可能会添加额外的处理。核心角色代理模式主要包含三个核心角色Subject (抽象主题)定义了真实对象和代理对象共同的接口客户端通过这个接口与代理和真实对象交互通常是一个抽象类或接口RealSubject (真实主题)被代理的实际对象执行业务的核心逻辑实现Subject定义的接口Proxy (代理)持有对真实对象的引用实现了抽象主题接口可以在调用真实对象前后执行额外的操作控制对真实对象的访问为什么要使用代理模式代理模式的价值在于它可以在不改变真实对象代码的前提下为其增加额外的功能。这些功能通常是通用的、与核心业务无关的例如远程代理 (Remote Proxy)为一个位于不同地址空间的对象提供本地的代表可以隐藏网络通信的细节使得客户端调用远程对象就像调用本地对象一样示例Dubbo、gRPC等RPC框架的客户端存根Stub就是典型的远程代理实现方式通常通过序列化/反序列化和网络通信来实现虚拟代理 (Virtual Proxy)根据需要创建开销很大的对象如果真实对象创建和初始化非常耗时虚拟代理可以延迟它的创建示例加载一个高清大图可以先显示一个占位符代理在后台真正加载图片真实对象实现方式懒加载模式保护代理/安全代理 (Protection Proxy)控制对真实对象的访问权限代理可以根据调用者的权限决定是否将请求转发给真实对象示例Spring Security中实现的方法级别的权限控制实现方式权限检查和访问控制列表智能引用 (Smart Reference)在访问对象时执行一些附加操作如缓存、日志记录、事务管理等示例Spring AOP中的切面编程实现方式通过方法拦截和增强代理模式在Java中的实现静态代理静态代理是在编译时就确定代理关系的代理方式实现步骤定义业务接口实现真实业务类创建代理类实现相同接口并持有真实对象的引用在代理类的方法中添加额外功能并调用真实对象的方法示例代码// 1. 定义接口interfaceImage{voiddisplay();}// 2. 真实对象classRealImageimplementsImage{privateStringfilename;publicRealImage(Stringfilename){this.filenamefilename;loadFromDisk();}privatevoidloadFromDisk(){System.out.println(Loading filename);}publicvoiddisplay(){System.out.println(Displaying filename);}}// 3. 代理类classProxyImageimplementsImage{privateRealImagerealImage;privateStringfilename;publicProxyImage(Stringfilename){this.filenamefilename;}publicvoiddisplay(){if(realImagenull){realImagenewRealImage(filename);// 延迟加载}System.out.println(Proxy doing some pre-processing);realImage.display();System.out.println(Proxy doing some post-processing);}}// 使用publicclassMain{publicstaticvoidmain(String[]args){ImageimagenewProxyImage(test.jpg);image.display();// 第一次会加载image.display();// 直接使用已加载的图片}}特点代理类和真实类在编译时就确定了一个代理类只能代理一个接口需要为每个被代理的类创建对应的代理类代码冗余维护成本高动态代理动态代理是在运行时动态生成代理类的代理方式Java提供的实现方式JDK动态代理基于接口CGLIB动态代理基于类JDK动态代理要求被代理的类必须实现至少一个接口使用java.lang.reflect.Proxy类和InvocationHandler接口示例代码// 1. 定义接口interfaceSubject{voidrequest();}// 2. 真实对象classRealSubjectimplementsSubject{publicvoidrequest(){System.out.println(RealSubject handling request);}}// 3. 实现InvocationHandlerclassDynamicProxyHandlerimplementsInvocationHandler{privateObjectrealSubject;publicDynamicProxyHandler(ObjectrealSubject){this.realSubjectrealSubject;}publicObjectinvoke(Objectproxy,Methodmethod,Object[]args)throwsThrowable{System.out.println(Before calling method.getName());Objectresultmethod.invoke(realSubject,args);System.out.println(After calling method.getName());returnresult;}}// 使用publicclassMain{publicstaticvoidmain(String[]args){RealSubjectrealnewRealSubject();Subjectproxy(Subject)Proxy.newProxyInstance(Subject.class.getClassLoader(),newClass[]{Subject.class},newDynamicProxyHandler(real));proxy.request();}}CGLIB动态代理可以代理没有实现接口的类通过继承被代理类来实现代理示例代码// 1. 真实对象不需要实现接口classRealSubject{publicvoidrequest(){System.out.println(RealSubject handling request);}}// 2. 实现MethodInterceptorclassCglibProxyimplementsMethodInterceptor{publicObjectintercept(Objectobj,Methodmethod,Object[]args,MethodProxyproxy)throwsThrowable{System.out.println(Before calling method.getName());Objectresultproxy.invokeSuper(obj,args);System.out.println(After calling method.getName());returnresult;}}// 使用publicclassMain{publicstaticvoidmain(String[]args){EnhancerenhancernewEnhancer();enhancer.setSuperclass(RealSubject.class);enhancer.setCallback(newCglibProxy());RealSubjectproxy(RealSubject)enhancer.create();proxy.request();}}动态代理的特点代理关系在运行时确定一个代理类可以代理多个接口/类减少了代码冗余性能略低于静态代理因为涉及反射调用更加灵活易于扩展静态代理与动态代理的区别特性静态代理动态代理创建时机编译时运行时代理关系固定灵活代理类数量每个被代理类需要一个代理类一个代理类可以代理多个类性能较高直接调用略低反射调用实现复杂度简单较复杂适用场景代理关系简单、固定代理关系复杂、多变对被代理类要求无特殊要求JDK代理需要实现接口CGLIB不能代理final类代码冗余高低实际应用场景Spring框架中的AOP基于动态代理实现面向切面编程对方法调用进行拦截和增强实现事务管理、日志记录、权限控制等横切关注点MyBatis的Mapper接口通过JDK动态代理生成Mapper接口的实现类将接口方法调用转换为SQL执行RPC框架客户端使用代理来封装远程调用细节服务端使用代理来处理请求并调用实际服务Hibernate的延迟加载使用动态代理实现关联对象的延迟加载当真正访问对象属性时才从数据库加载数据Spring Security使用代理实现方法级别的安全控制在方法调用前进行权限检查