Java 代理模式 (Proxy)详解

代理模式(proxy) 代理模式(proxy) 代理模式:为其他对象提供一种代理以控制对这个对象的访问。 代理模式的应用 一、远程代理,也就是为了一个对象在不同的地址空间提供局部代表,这样可以隐藏一个对象存在于不同地址空间的事实。 二、虚拟代理,是根据需要创建开销很大的对象。通过它来存放实例化需要很长时间的真实对象。这样可以达到性能最优化。 三、安全代理,用来控制真实对象访问时的权限。 四、智能指引,是指... 阅读详情

一、什么是代理模式?

  • 定义: 代理模式是一种结构型设计模式。 它为另一个对象(目标对象/被代理对象)提供一个代理(或占位符),以控制对这个对象的访问。
  • 核心思想: 通过引入一个代理对象,客户端不直接访问目标对象,而是通过代理对象来间接访问目标对象。 代理对象可以控制对目标对象的访问,并可以在访问前后添加额外的操作。
  • 意图: 控制对一个对象的访问,可以延迟加载、访问控制、增强功能等。

二、代理模式的结构

代理模式通常包含以下几个角色:

  1. Subject (抽象主题):

    • 定义了 RealSubject 和 Proxy 的共同接口。 客户端通过 Subject 接口访问目标对象。
    • 通常是一个接口或抽象类。
  2. RealSubject (真实主题/目标对象/被代理对象):

    • 定义了真正的业务逻辑。
    • 实现了 Subject 接口。
  3. Proxy (代理):

    • 持有 RealSubject 对象的引用。
    • 实现了 Subject 接口,与 RealSubject 具有相同的方法。
    • 控制对 RealSubject 对象的访问,并可以在访问前后添加额外的操作。
    • 客户端通过 Proxy 对象间接访问 RealSubject 对象。

UML 类图:

+----------------+       +----------------+       +----------------+
|   <<Subject>>   |       |     Proxy      |       |  RealSubject   |
+----------------+       +----------------+       +----------------+
| +request()     |------>| -realSubject   |------>| +request()     |
+----------------+       | +request()     |       +----------------+
                             +preRequest()
                             +postRequest()

三、代理模式的类型

根据代理的创建时间和功能,可以将代理模式分为以下几种类型:

  1. 静态代理 (Static Proxy):

    • 特点: 在编译时就已经确定了代理类和被代理类之间的关系。 代理类和被代理类都需要实现相同的接口。
    • 优点: 实现简单,易于理解。
    • 缺点:
      • 代码冗余: 如果需要代理多个类,就需要创建多个代理类,导致代码冗余。
      • 可维护性差: 如果接口发生变化,代理类和被代理类都需要进行修改。
  2. 动态代理 (Dynamic Proxy):

    • 特点: 在运行时动态地生成代理类,无需手动创建代理类。
    • 优点:
      • 灵活性高: 可以代理任何实现了接口的类,无需修改原始代码。
      • 代码复用: 可以使用同一个代理类来代理多个不同的类。
      • 可维护性好: 如果接口发生变化,只需要修改代理逻辑,无需修改被代理类。
    • 缺点:
      • 实现复杂: 动态代理的实现比静态代理复杂。
      • 性能开销: 动态代理需要使用反射机制,性能比静态代理略低。
    • Java 中的动态代理:
      • JDK 动态代理: Java 提供的内置动态代理机制,只能代理实现了接口的类。
      • CGLIB 动态代理: 第三方库提供的动态代理机制,可以代理没有实现接口的类。
  3. 其他代理

    • 保护代理 用于控制对敏感对象的访问。
    • 远程代理 用于访问远程对象。
    • 虚拟代理 通过代理延迟创建开销大的对象

四、代理模式的实现方式 (Java)

  1. 静态代理:

    // 抽象主题
    interface Image {
        void display();
    }
    
    // 真实主题
    class RealImage implements Image {
        private String filename;
    
        public RealImage(String filename) {
            this.filename = filename;
            loadImageFromDisk();
        }
    
        private void loadImageFromDisk() {
            System.out.println("Loading image: " + filename);
        }
    
        @Override
        public void display() {
            System.out.println("Displaying image: " + filename);
        }
    }
    
    // 代理
    class ImageProxy implements Image {
        private RealImage realImage;
        private String filename;
    
        public ImageProxy(String filename) {
            this.filename = filename;
        }
    
        @Override
        public void display() {
            if (realImage == null) {
                realImage = new RealImage(filename);
            }
            realImage.display();
        }
    }
    
    // 客户端代码
    public class StaticProxyExample {
        public static void main(String[] args) {
            Image image = new ImageProxy("test_image.jpg");
    
            // 第一次调用 display() 方法,会加载图片
            image.display();
    
            // 第二次调用 display() 方法,不会再次加载图片
            image.display();
        }
    }
    
  2. JDK 动态代理:

    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    import java.lang.reflect.Proxy;
    
    // 抽象主题
    interface Image {
        void display();
    }
    
    // 真实主题
    class RealImage implements Image {
        private String filename;
    
        public RealImage(String filename) {
            this.filename = filename;
            loadImageFromDisk();
        }
    
        private void loadImageFromDisk() {
            System.out.println("Loading image: " + filename);
        }
    
        @Override
        public void display() {
            System.out.println("Displaying image: " + filename);
        }
    }
    
    // 调用处理器
    class ImageInvocationHandler implements InvocationHandler {
        private Object target; // 被代理的对象
    
        public ImageInvocationHandler(Object target) {
            this.target = target;
        }
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            // 在调用目标方法之前执行的操作
            System.out.println("Before invoking method: " + method.getName());
    
            // 调用目标方法
            Object result = method.invoke(target, args);
    
            // 在调用目标方法之后执行的操作
            System.out.println("After invoking method: " + method.getName());
    
            return result;
        }
    }
    
    // 客户端代码
    public class JDKDynamicProxyExample {
        public static void main(String[] args) {
            // 创建被代理对象
            Image realImage = new RealImage("test_image.jpg");
    
            // 创建调用处理器
            ImageInvocationHandler handler = new ImageInvocationHandler(realImage);
    
            // 创建代理对象
            Image proxy = (Image) Proxy.newProxyInstance(
                    Image.class.getClassLoader(), // 类加载器
                    new Class[] {Image.class}, // 代理类实现的接口列表
                    handler // 调用处理器
            );
    
            // 通过代理对象调用方法
            proxy.display();
        }
    }
    
  3. CGLIB 动态代理:

    import net.sf.cglib.proxy.Enhancer;
    import net.sf.cglib.proxy.MethodInterceptor;
    import net.sf.cglib.proxy.MethodProxy;
    
    import java.lang.reflect.Method;
    
    // 真实主题 (不需要实现接口)
    class RealImage {
        private String filename;
    
        public RealImage(String filename) {
            this.filename = filename;
            loadImageFromDisk();
        }
        public RealImage(){} //需要一个无参构造函数
    
        private void loadImageFromDisk() {
            System.out.println("Loading image: " + filename);
        }
    
        public void display() {
            System.out.println("Displaying image: " + filename);
        }
    }
    
    // 方法拦截器
    class ImageMethodInterceptor implements MethodInterceptor {
        @Override
        public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
            // 在调用目标方法之前执行的操作
            System.out.println("Before invoking method: " + method.getName());
    
            // 调用目标方法
            Object result = proxy.invokeSuper(obj, args);
    
            // 在调用目标方法之后执行的操作
            System.out.println("After invoking method: " + method.getName());
    
            return result;
        }
    }
    
    // 客户端代码
    public class CGLIBDynamicProxyExample {
        public static void main(String[] args) {
            // 创建 Enhancer 对象
            Enhancer enhancer = new Enhancer();
    
            // 设置超类
            enhancer.setSuperclass(RealImage.class);
    
            // 设置回调
            enhancer.setCallback(new ImageMethodInterceptor());
    
            // 创建代理对象
            RealImage proxy = (RealImage) enhancer.create();
    
            // 通过代理对象调用方法
            proxy.display();
        }
    }
    

五、代理模式的优缺点

优点:

  • 职责清晰: 将客户端与目标对象分离,降低了耦合度。
  • 扩展性好: 可以通过添加新的代理类来扩展系统功能,而无需修改原始代码。
  • 保护目标对象: 代理对象可以控制对目标对象的访问,保护目标对象免受恶意访问。
  • 增强目标对象的功能: 代理对象可以在访问目标对象前后添加额外的操作,例如日志记录、安全检查、延迟加载等。

缺点:

  • 增加系统复杂性: 引入代理对象会增加系统的复杂性。
  • 可能降低性能: 代理对象需要进行额外的处理,可能会降低程序的性能。

六、代理模式的应用场景

  • 远程代理 (Remote Proxy): 为远程对象提供一个本地代理,隐藏远程对象的具体实现细节。
  • 虚拟代理 (Virtual Proxy): 为创建开销大的对象提供一个代理,延迟对象的创建,直到真正需要使用时才创建。
  • 保护代理 (Protection Proxy): 控制对敏感对象的访问,只允许具有特定权限的客户端访问。
  • 缓存代理 (Cache Proxy): 为访问开销大的对象提供一个缓存,提高访问效率。
  • 智能引用代理 (Smart Reference Proxy): 在访问对象时执行额外的操作,例如引用计数、对象锁定等。
  • AOP (面向切面编程): 使用动态代理来实现 AOP,例如 Spring AOP。
  • 延迟加载 (Lazy Loading): 例如,Hibernate 中的延迟加载机制。
  • 防火墙代理: 控制网络访问,保护内部网络。

七、总结

代理模式是一种非常有用的设计模式,它可以控制对对象的访问,并可以在访问前后添加额外的操作。 在 Java 中,可以使用静态代理、JDK 动态代理和 CGLIB 动态代理来实现代理模式。 选择哪种实现方式取决于具体的应用场景和需求。

【Java设计模式】Java设计模式之(十八)代理模式(Proxy Pattern) 这种类型的设计模式属于结构型模式。 一、适配器模式介绍 1.1 含义 代理模式(Proxy Pattern),一个类代表另一个类的功能。 在代理模式中,我们创建具有现有对象的对象,以便向外界提供功能接口。 1.2 适用场景 按职责来划分,通常有以下使用场景: ① 远程代理。 ② 虚拟代理。 ③ Copy-on-Write 代理。 ④ 保护(Protect or Access)代理。 ⑤ Cache代理。 ⑥ 防火墙(Firewall)代理。 ⑦ 同步化(Synchronizatio 阅读详情

相关推荐

Java设计模式——代理设计模式(静态代理和动态代理)

Java设计模式——代理设计模式(静态代理和动态代理) 各种情况例子源码

【Java】代理模式(Proxy模式)详解

Java代理模式详解

Passer_hua的博客 2万+

HC32F460的GPIO重映射实战:如何用3步搞定SPI引脚冲突问题

本文详细介绍了HC32F460的GPIO重映射功能,通过三步操作解决SPI引脚冲突问题。文章解析了HC32F460的FuncGroup功能分组机制,提供了具体的寄存器配置步骤和验证技巧,并对比了与传统方案的性能优势,帮助工程师灵活配置引脚,优化硬件设计。

t4y5u6i7o的博客 920

Java设计模式-代理模式

Java设计模式之一的代理模式,介绍了静态代理模式和动态代理,动态代理介绍了JDK动态代理和Cglib动态代理。

m0_62946761的博客 5422

SARscape的DInSAR全流程-以西安市隋大兴唐长安城遗址为例

通过DInSAR对西安市隋大兴唐长安城遗址开展的年度周期性监测,发现成因是地质内部构造断裂带活动所导致的地面产生物理空间上的形变,而地面的沉降与抬升是直接影响城市发展与文化遗产保护最为常见的缓变型不可逆地质灾害。西安市地处汾渭断陷盆地中部,受临潼-长安断裂带影响,导致区域内构造活动较为强烈。由于早年西安市地表水资源匮乏,从上世纪50年代末开始大量开采地下水资源以满足城市人口不断扩张的需求,从而导致地下承压含水层水位急速下降,形成多个局部沉降中心(八里村、西工大、电子城等)。

2301_77687129的博客 5816

JDK8升级JDK17过程中遇到的那些坑

JDK8虽然非常好,但是JDK版本已经发布到JDK20了,且JDK8后的版本升级了很多新的特性,如模块化、ZGC以及虚拟线程、结构性并发等,也是非常有吸引力的,所以决定将基于JDK8的项目升级到最近的LTS版本JDK17。

BASK2312的博客 6686

Java 设计模式-代理模式

代理模式(Proxy Pattern)是设计模式中的一种结构型模式,其核心思想是通过创建一个代理对象来间接访问实际对象(也称为主题对象),从而在不改变实际对象的前提下,为实际对象添加额外的功能或控制。代理模式根据实现方式可分:某个类必须有实现的接口,如果某个类没有实现接口,那么这个类就不能通过 JDK 产生动态代理了静态代理动态代理。

精神小牛马 3730

SD - WAN:企业出海的网络加速器

例如,一家中国的跨境电商企业,在欧美市场的促销活动期间,借助 SD - WAN 技术,即使面对海量订单数据的交互,也能确保欧美客户在浏览商品、下单支付时感受到近乎本地网络的流畅体验,大大提升了客户满意度,稳住了销售增速。企业无需在海外本地部署大量冗余服务器,只需依托云台,借助 SD - WAN 快速稳定的网络连接,即可轻松实现业务拓展,进一步精简运营架构,提升整体效能。在未来,随着技术的不断演进和企业出海需求的持续增长,SD - WAN 将持续赋能,助力更多企业在全球市场扬帆远航,书写辉煌篇章。

idcicp_com的博客 447

Java 静态代理、Java动态代理、CGLIB动态代理

转载 作者:树修 原文:https://www.jianshu.com/p/1682ed0d0c16 Java 的代理就是客户类不再直接和委托类打交道, 而是通过一个中间层来访问, 这个中间层就是代理。为啥要这样呢, 是因为使用代理有 2 个优势: 可以隐藏委托类的实现 可以实现客户与委托类之间的解耦, 在不修改委托类代码的情况下能够做一些额外的处理 我们举个...

qiang_zi_的专栏 737

Creo报许可证错误License request failed for feature的解决方案

有些朋友用了一段时间打开creo软件,出现icense request failed for feature”错误,这个是Creo许可证出现了问题,一般是许可证文件无效或是已过期,导致Creo软件通信出现故障,就会出现Creo License request failed for feature, Requsesting CreoPMA_SSQ ,Run ptcstatus.bat server status。第三步:键盘按win+R,在运行窗口里输入:cmd,然后点确定。第八步:点击系统,找到系统信息。

Q82556499的博客 3万+

渗透测试实战—云渗透(AK/SK泄露)

渗透测试实战思路分享:getshell方法及横向移动方法,云安全(AK/SK泄露)

网安日记本的博客 4051

Java代理模式之静态代理模式(Static Proxy)详解

文章目录1.定义2.举例说明3.代码组成部分4.以申请学校为例具体讲解 1.定义 代理模式为某个对象提供一个代理,以控制对这个对象的访问。代理类和委托类有共同的父类或父接口,这样在任何使用委托类对象的地方都可以用代理对象替代。代理类负责请求的预处理、过滤、将请求分派给委托类处理、以及委托类执行完请求后的后续处理。 2.举例说明 现实生活中有许多与Java静态代理模式相仿的例子 先从名称看来,代...

Kevin.wang 949

python批量调用大模型API:多线程和异步协程

本文介绍了利用多线程技术批量调用大模型API的实现方法。核心是通过并发请求提高处理效率,主要采用线程池管理并发数量、结果聚合等技术。文章提供了一个完整的Python实现示例,包含APIBatchCaller类及其single_api_call和batch_call方法,详细解析了并发控制、错误处理等关键点,并给出了使用注意事项,包括并发数设置、重试策略和超时处理等。该方案特别适合IO密集型任务,能显著提升批量API调用的效率。

Cachel Wood的博客 760

Java开发中的23种设计模式详解----代理模式(Proxy)

其实每个模式名称就表明了该模式的作用,代理模式就是多一个代理类出来,替原对象进行一些操作,比如我们在租房子的时候回去找中介,为什么呢?因为你对该地区房屋的信息掌握的不够全面,希望找一个更熟悉的人去帮你做,此处的代理就是这个意思。再如我们有的时候打官司,我们需要请律师,因为律师在法律方面有专长,可以替我们进行操作,表达我们的想法。先来看看关系图:   public interface

sjyttkl的专栏 859

【芯片设计- 芯片生产及测试 11.2 -- memory repair 详细介绍】

SoC (System on Chip) 的 Memory Repair 是一种技术,用于检测和修复内存中的损坏单元。由于SoC内部集成了大量的逻辑和存储单元,包括RAM(随机访问存储器)、ROM(只读存储器)、缓存等,在制造过程中,由于工艺偏差或材料缺陷,有可能产生一些损坏的内存位。Memory Repair 机制允许系统检测这些错误并采取措施纠正,以提高芯片的产量和可靠性。

CodingCos的博客 3226

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

编程自学指南:java程序设计开发,Java 代理模式(Proxy)详解,代理模式的核心思想:控制对象访问,静态代理与动态代理的实现方法,代理模式实现日志、事务等横切功能

编程自学指南:java程序设计开发,Java 代理模式(Proxy)详解,代理模式的核心思想:控制对象访问,静态代理与动态代理的实现方法,代理模式实现日志、事务等横切功能

zl515035644的博客 529

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

设计模式:代理模式

为什么要使用代理模式: 比较官方的回答:在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用,其特征是代理类与委托类有同样的接口。代理模式是常用的java设计模式。 看完这个解释依然云里雾里,我觉得代理除了上述功能,最易理解的是,在原有代码的基础上增加功能时,不会修改原有代码,非常符合程序设计的开闭原则。 代理模式一般分为静态代理和动态...

EnseHeiKe的博客 268

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

代理模式详解

【Java】代理模式(Proxy模式)详解 - 百度文库

最爱奶油花生 381

Java代理模式详细

代理模式是一种非常有用的设计模式,它可以在不修改原始类代码的情况下,通过引入代理类来给原始类附加额外的功能或控制。在Java中,静态代理和动态代理是实现代理模式的两种主要方式,它们各自适用于不同的场景。理解并掌握代理模式对于提高代码的可维护性和可扩展性具有重要意义。

2401_83447580的博客 527

设计模式之代理模式ProxyPattern(六)

1、什么是代理模式?代理模式是23种设计模式中的一种。代理模式是一种结构型设计模式,它允许为其他对象提供一个替代品或占位符,以控制对这个对象的访问。2、代理模式的角色构成抽象主题(Subject):定义了真实主题和代理主题的共同接口,这样代理类可以通过实现该接口来代理真实主题。真实主题(Real Subject):定义了代理所代表的真实对象。代理(Proxy):持有对真实主题的引用,并实现了与真实主题一样的接口,客户端通过代理来访问真实主题,同时可以在访问真实主题前后进行一些额外操作。

徐泗空的博客 1465

Java代理模式的实现详解

本文章是在学习mybatis框架源码的过程中,发现对于动态代理Mapper接口这一块的代理实现还是有些遗忘和陌生,因此在本文章中就Java实现代理模式的过程进行一个学习和总结。代理模式(Proxy Pattern)定义:给某一个对象提供一个代理,并由代理对象控制对原对象的引用。代理模式的英文叫做Proxy或Surrogate,它是一种对象结构型模式。

Bananaaay的博客 2261

Java代理模式详解

动态代理中,InvocationHandler 和Proxy是核心Proxy,这个方法主要用来生成一个代理对象。Class<?....../**这个方法一共有 3 个参数:loader :类加载器,用于加载代理对象。interfaces : 被代理类实现的一些接口;h : 实现了 InvocationHandler 接口的对象;**/要实现动态代理的话,还必须需要实现来自定义处理逻辑。当我们的动态代理对象调用一个方法时,这个方法的调用就会被转发到实现接口类的invoke方法来调用。/**

七禾页话的博客 1415

代理模式-ProxyPattern

前言: 代理模式与装饰者模式: 相同点: 1. 前提条件:装饰者(代理者)与被装饰者(委托者)要继承相同的父类或实现相同的接口。 2. 都可以增强某个类的方法,对程序进行扩展。 不同点: 1. 代理者是为某个对象添加一个代理,以控制对这个对象的访问。而装饰者增强某个类的方法。 2. 代理可以在调用核心方法之前做前置处理...

Jason Blog 197

JAVA 代理模式(Proxy)

1.代理模式代理模式的作用是:为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个客户不想或者不能直接引用另一个对象,而代理对象可以在客户端和目标对象之间起到中介的作用。代理模式一般涉及到的角色有:抽象角色:声明真实对象和代理对象的共同接口;代理角色:代理对象角色内部含有对真实对象的引用,从而可以操作真实对象,同时代理对象提供与真实对象相同的接口以便在任何时刻都能代替真实对象。同时,代

jianghuxiaoxiami的专栏 3万+

Java —— Proxy 代理模式

Java —— 代理模式

Genius only means hard-working all one's life. 534
上一篇: Java 反射 (Reflection) 详解
下一篇: 策略模式 (Strategy)详解
冰糖心书房
博客等级 码龄15年 6019粉丝 690原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

冰糖心书房

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值