Java 代理模式详解,静态代理与动态代理的区别及优缺点

这篇具有很好参考价值的文章主要介绍了Java 代理模式详解,静态代理与动态代理的区别及优缺点。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

代理模式是一种常用的设计模式,它允许通过引入一个代理对象来控制对目标对象的访问。在Java中,代理模式被广泛应用,它可以提供额外的功能,如权限检查、缓存、日志记录等,同时还能在不修改目标对象的情况下对其进行扩展。

1. 代理模式的定义

代理模式(Proxy Pattern)是指通过代理对象控制对目标对象的访问,并在不改变目标对象的情况下添加额外的功能或控制访问。代理对象和目标对象实现相同的接口,使得客户端可以通过代理对象间接地访问目标对象。

代理模式属于结构型设计模式,它在系统中引入了一个代理对象,该对象代替了客户端直接访问目标对象,从而可以在目标对象的基础上增加一些额外的功能或控制访问。

2. 代理模式的原理

代理模式的核心思想是引入一个代理对象来控制对目标对象的访问。代理对象和目标对象实现相同的接口,使得客户端可以通过代理对象间接地访问目标对象。代理对象负责处理客户端的请求,并在必要时将请求转发给目标对象。在这个过程中,代理对象可以添加额外的逻辑,如权限检查、缓存、日志记录等。

代理模式的主要角色有:

  • 抽象主题(Subject):定义了代理对象和目标对象的共同接口,在Java中通常是一个接口或抽象类。
  • 目标对象(RealSubject):定义了代理对象所代表的真实对象,是业务逻辑的具体执行者。
  • 代理对象(Proxy):持有对目标对象的引用,并实现了与目标对象相同的接口,在方法调用前后进行额外操作。

代理模式的工作流程如下:

  1. 客户端向代理对象发送请求。
  2. 代理对象收到请求后,可以在请求被转发给目标对象之前或之后执行一些额外的逻辑。
  3. 代理对象将请求转发给目标对象。
  4. 目标对象执行具体的业务逻辑并返回结果。
  5. 代理对象可以在目标对象返回结果之前或之后执行一些额外的操作。
  6. 代理对象将结果返回给客户端。

通过引入代理对象,代理模式可以控制对目标对象的访问,并在不改变目标对象的情况下添加额外的功能或控制访问。

3. 代理模式的实现方式

在Java中,代理模式主要有两种实现方式:静态代理和动态代理。

3.1 静态代理

静态代理是指在编译时就已经确定了代理对象和目标对象的关系,代理类是通过手动编写代码来实现的。在静态代理中,代理类和目标类都实现相同的接口,代理类持有目标对象,并在方法调用前后进行额外的操作。

静态代理的工作原理如下:

  1. 定义一个接口(或抽象类)作为目标接口,目标对象实现这个接口。
  2. 创建一个代理类,实现目标接口,并持有目标对象的引用。
  3. 在代理类中重写目标接口的方法,在方法调用前后执行需要的额外操作。
  4. 客户端使用代理对象来访问目标对象。

静态代理的特点:

  • 需要手动编写代理类,工作量较大。
  • 目标对象必须实现接口。
  • 代理类和目标类的关系在编译时就确定了,无法动态改变。

静态代理的应用场景:

  • 安全控制:代理类可以在调用目标方法前进行权限检查等安全控制。
  • 远程调用:代理类可以封装网络通信相关的细节,使得调用远程方法就像调用本地方法一样简单。
  • 性能监控:代理类可以收集方法的执行时间、调用次数等信息,用于性能监控和统计分析。

下面是一个简单的静态代理的示例代码:

// 定义接口
public interface Image {
    void display();
}

// 目标类
public class RealImage implements Image {
    private String filename;

    public RealImage(String filename) {
        this.filename = filename;
        loadFromDisk();
    }

    private void loadFromDisk() {
        System.out.println("Loading image: " + filename);
    }

    @Override
    public void display() {
        System.out.println("Displaying image: " + filename);
    }
}

// 代理类
public class ImageProxy implements Image {
    private String filename;
    private RealImage realImage;

    public ImageProxy(String filename) {
        this.filename = filename;
    }

    @Override
    public void display() {
        if (realImage == null) {
            realImage = new RealImage(filename);
        }
        realImage.display();
    }
}

// 测试类
public class ProxyPatternDemo {
    public static void main(String[] args) {
        // 使用代理对象显示图片
        Image image = new ImageProxy("test.jpg");
        image.display();
        
        // 图片已加载,直接显示,无需重新加载
        image.display();
    }
}

在上面的示例中,Image 是一个接口,RealImage 是目标类,负责加载和显示图片。ImageProxy 是代理类,通过持有目标类的引用,在需要时创建并使用目标类。ProxyPatternDemo 是一个测试类,用于演示静态代理的使用。

在测试类中,首先创建一个代理对象 ImageProxy,并调用 display() 方法显示图片。代理对象会在第一次调用 display() 方法时,创建真实对象 RealImage 并调用其 display() 方法加载和显示图片。在后续调用 display() 方法时,代理对象直接调用真实对象的 display() 方法,无需重新加载图片。

静态代理的缺点是需要手动编写代理类,工作量较大。如果接口中的方法较多或频繁变动,就需要频繁修改代理类的代码,增加了维护的难度。此外,静态代理的代理类和目标类之间存在紧耦合关系,一旦目标类发生变化,代理类也需要相应修改。

为了解决静态代理的缺点,Java还提供了动态代理机制。

3.2 动态代理

动态代理是指在运行时生成代理对象,而无需手动编写代理类。Java的动态代理机制是基于反射实现的,通过使用java.lang.reflect.Proxy类和java.lang.reflect.InvocationHandler接口来实现动态代理。

在动态代理中,代理类的创建和方法调用都是在运行时完成的。代理对象是在内存中动态创建的,并实现了目标对象的接口,同时持有目标对象的引用。在方法调用时,代理对象通过调用InvocationHandler接口中的方法来处理请求,可以在方法调用前后执行额外的操作。

动态代理的工作原理如下:

  1. 定义一个接口,作为目标接口。
  2. 创建一个InvocationHandler接口的实现类,该类负责处理方法调用并执行额外的操作。
  3. 使用Proxy类的静态方法newProxyInstance()生成代理对象,同时指定目标对象和InvocationHandler
  4. 客户端使用代理对象来访问目标对象的方法。

动态代理的特点:

  • 不需要手动编写代理类,代理对象在运行时动态生成。
  • 目标对象可以不实现接口,只需定义目标对象的共同接口。
  • 代理对象和目标对象的关系在运行时确定,可以动态改变。

动态代理的应用场景:

  • AOP(面向切面编程):动态代理可以在目标方法执行前后执行额外的操作,如权限检查、事务管理等。它是实现AOP的一种常见方式。
  • 延迟加载:动态代理可以在目标方法被调用时才进行加载和初始化,实现延迟加载的效果。
  • 日志记录:动态代理可以在目标方法执行前后记录日志信息。

下面是一个简单的动态代理的示例代码:

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;
        loadFromDisk();
    }

    private void loadFromDisk() {
        System.out.println("Loading image: " + filename);
    }

    @Override
    public void display() {
        System.out.println("Displaying image: " + filename);
    }
}

// InvocationHandler 实现类
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 method: " + method.getName());
        Object result = method.invoke(target, args);
        System.out.println("After method: " + method.getName());
        return result;
    }
}

// 测试类
public class ProxyPatternDemo {
    public static void main(String[] args) {
        // 创建目标对象
        Image realImage = new RealImage("test.jpg");

        // 创建 InvocationHandler 实例
        ImageInvocationHandler handler = new ImageInvocationHandler(realImage);

        // 创建代理对象
        Image imageProxy = (Image) Proxy.newProxyInstance(Image.class.getClassLoader(),
                new Class[]{Image.class}, handler);

        // 使用代理对象显示图片
        imageProxy.display();
    }
}

在上面的示例中,Image 是一个接口,RealImage 是目标类,负责加载和显示图片。ImageInvocationHandlerInvocationHandler接口的实现类,用于处理方法调用并执行额外的操作。ProxyPatternDemo 是一个测试类,用于演示动态代理的使用。

在测试类中,首先创建一个目标对象 RealImage,然后创建一个 ImageInvocationHandler 实例,并将目标对象传入构造函数。接下来,通过调用 Proxy 类的 newProxyInstance() 方法来生成代理对象。最后,使用代理对象调用 display() 方法显示图片。

在方法调用时,代理对象会调用 InvocationHandler 接口中的 invoke() 方法处理方法调用。在示例中,我们在 invoke() 方法中实现了打印方法名的额外操作,并通过反射调用目标对象的方法。文章来源地址https://www.toymoban.com/news/detail-502923.html

到了这里,关于Java 代理模式详解,静态代理与动态代理的区别及优缺点的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Java代理模式——静态代理与动态代理

    代理模式允许你为其他对象提供一个代理,以控制对这个对象的访问。代理模式在不改变实际对象的情况下,可以在访问对象时添加额外的功能。 可以理解为代理模式为被代理对象创造了一个替身,调用者可以通过这个替身去实现这个被代理对象的功能,这个替身也可以为被

    2024年02月13日
    浏览(46)
  • 详解单体架构和微服务(概念,优缺点和区别)

    单体架构的整个系统是一个War包,即war包走天下。微服务架构的项目是很多个war包(一个子系统一个)。 单体架构的优点: 架构简单 开发测试部署简单 缺点: 随着业务扩展,代码越来越复杂,代码质量参差不齐,开发人员的水平不一,修改每一个小bug都是心惊胆战的。并且在

    2024年02月12日
    浏览(46)
  • 详解23种设计模式优缺点以及解决方案

    优点:确保一个类只有一个实例,提供全局访问点,节省资源。 缺点:可能引入全局状态,难以扩展和测试。 解决方法:使用依赖注入来替代直接访问单例对象,以便更好地控制依赖关系和测试。 优点:封装对象的创建,客户端代码与具体类解耦。 缺点:增加了代码复杂性

    2024年02月12日
    浏览(46)
  • 代理模式 静态代理和动态代理(jdk、cglib)——Java入职第十一天

            一个类代表另一个类去完成扩展功能,在主体类的基础上,新增一个代理类,扩展主体类功能,不影响主体,完成额外功能。比如买车票,可以去代理点买,不用去火车站,主要包括静态代理和动态代理两种模式。 代理类中包含了主体类 无法根据业务扩展,每一次

    2024年02月10日
    浏览(50)
  • 设计模式之代理模式(静态代理&动态代理)

    目录 1、什么是代理模式 2、代理模式的结构 3、代理模式的实现 3.1 静态代理和动态代理概念 3.2 静态代理 3.3 动态搭理 3.3.1 代码实现 3.3.2 Proxy类讲解 4、动态代理VS静态代理 5、代理模式优缺点 由于某些原因需要给某对象提供一个代理以控制对该对象的访问。这时,访问对象

    2024年02月03日
    浏览(38)
  • 代理模式--静态代理和动态代理

    定义:代理模式就是代替对象具备真实对象的功能,并代替真实对象完成相应的操作并且在不改变真实对象源代码的情况下扩展其功能,在某些情况下,⼀个对象不适合或者不能直接引⽤另⼀个对象,⽽代理对象可以在客户端和⽬标对象之间起到中介的作⽤ 使用代理模式可以

    2024年02月15日
    浏览(39)
  • 代理设计模式——静态代理和动态代理

    代理模式 在代理模式(Proxy Pattern)中,一个类代表另一个类的功能。这种类型的设计模式属于结构型模式,在代理模式中,我们创建具有现有对象的对象,以便向外界提供功能接口。 意图: 为其他对象提供一种代理以控制对这个对象的访问。 主要解决: 在直接访问对象时

    2024年02月13日
    浏览(44)
  • 代理模式:静态代理+JDK/CGLIB 动态代理

    代理模式是一种比较好理解的设计模式。简单来说就是 我们使用代理对象来代替对真实对象(real object)的访问,这样就可以在不修改原目标对象的前提下,提供额外的功能操作,扩展目标对象的功能。 代理模式的主要作用是扩展目标对象的功能,比如说在目标对象的某个方法

    2024年02月13日
    浏览(36)
  • 温故知新之:代理模式,静态代理和动态代理(JDK动态代理)

    代理模式可以在不修改被代理对象的基础上,通过扩展代理类,进行一些功能的附加与增强。 静态代理 是一种代理模式的实现方式,它在编译期间就已经确定了代理对象,需要为每一个被代理对象创建一个代理类。静态代理的实现比较简单,但是每个被代理对象都需要创建

    2024年02月11日
    浏览(48)
  • 代理模式【静态代理和动态代理实现业务功能扩展】

    我们在不修改业务的情况下想要给它增加一些功能,这就需要使用代理模式。 我们不会在原有业务上直接修改,为了避免修改导致程序不可逆转的破坏。 三种角色:抽象角色-接口、真实角色-实现类和代理角色-代理类。 真实角色和代理角色继承的是同一个抽象角色接口!

    2024年02月16日
    浏览(32)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包