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

Java 怎样实现代理模式,有什么优缺点

一、介绍

代理模式是一种常见的设计模式,它可以为其他对象提供一种代理以控制对这个对象的访问。代理对象具有与被代理对象相同的接口,客户端无需知道代理对象和被代理对象的区别。代理模式可以应用于各种不同的场景,例如远程代理、虚拟代理、保护代理等。本文将介绍 Java 中代理模式的实现方式和优缺点,并提供相应的代码示例。

在这里插入图片描述

二、Java 中代理模式的实现方式

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

静态代理

静态代理是指在代码编译期间就已经确定代理类和被代理类的关系,代理类和被代理类的接口是相同的。静态代理需要手动编写代理类,因此代码量较大,但是在运行时代理对象的性能较高。下面是一个简单的静态代理代码示例:

首先定义一个接口 Subject:

public interface Subject {
    void request();
}

然后定义一个被代理类 RealSubject:

public class RealSubject implements Subject {
    @Override
    public void request() {
        System.out.println("RealSubject is doing something.");
    }
}

最后定义一个代理类 Proxy:

public class Proxy implements Subject {
    private RealSubject realSubject;

    public Proxy(RealSubject realSubject) {
        this.realSubject = realSubject;
    }

    @Override
    public void request() {
        System.out.println("Before the request.");
        realSubject.request();
        System.out.println("After the request.");
    }
}

在客户端使用时,可以直接使用代理对象调用方法:

Subject subject = new Proxy(new RealSubject());
subject.request();

输出结果为:

Before the request.
RealSubject is doing something.
After the request.

动态代理

动态代理是指在运行时动态生成代理类,不需要手动编写代理类。Java 中提供了两种动态代理的实现方式:基于接口的动态代理(JDK 动态代理)和基于类的动态代理(CGLIB 动态代理)。

(1)基于接口的动态代理

基于接口的动态代理是指代理类实现被代理类的接口,使用 Java 提供的 Proxy 类生成代理对象。在使用基于接口的动态代理时,被代理类必须实现一个接口,代理类会实现该接口并将方法的调用转发给被代理类。下面是一个简单的基于接口的动态代理代码示例:

首先定义一个接口 Subject:

public interface Subject {
    void request();
}

然后定义一个被代理类 RealSubject:

public class RealSubject implements Subject {
    @Override
    public void request() {
        System.out.println("RealSubject is doing something.");
    }
}

最后定义一个 InvocationHandler 类:

public class MyInvocationHandler implements InvocationHandler {
    private Object target;

    public MyInvocationHandler(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("Before the request.");
        Object result = method.invoke(target, args);
        System.out.println("After the request.");
        return result;
    }
}

在客户端使用时,可以通过 Proxy.newProxyInstance 方法生成代理对象:

Subject subject = (Subject) Proxy.newProxyInstance(
        Subject.class.getClassLoader(),
        new Class[] { Subject.class },
        new MyInvocationHandler(new RealSubject())
);
subject.request();

输出结果为:

Before the request.
RealSubject is doing something.
After the request.

(2)基于类的动态代理

基于类的动态代理是指代理类继承被代理类,使用 CGLIB 库生成代理对象。在使用基于类的动态代理时,被代理类不需要实现接口,代理类会继承被代理类并重写其方法,将方法的调用转发给被代理类。下面是一个简单的基于类的动态代理代码示例:

首先定义一个被代理类 RealSubject:

public class RealSubject {
    public void request() {
        System.out.println("RealSubject is doing something.");
    }
}

然后定义一个 MethodInterceptor 类:

public class MyMethodInterceptor implements MethodInterceptor {
    @Override
    public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
        System.out.println("Before the request.");
        Object result = proxy.invokeSuper(obj, args);
        System.out.println("After the request.");
        return result;
    }
}

在客户端使用时,可以通过 Enhancer.create 方法生成代理对象:

Enhancer enhancer = new Enhancer();
enhancer.setSuperclass(RealSubject.class);
enhancer.setCallback(new MyMethodInterceptor());
RealSubject subject = (RealSubject) enhancer.create();
subject.request();

输出结果为:

Before the request.
RealSubject is doing something.
After the request.

三、Java 中代理模式的优缺点

代理模式在 Java 中的应用非常广泛,其优缺点如下:

优点

(1)代理模式可以隐藏被代理对象的实现细节,使得客户端无需直接访问被代理对象,从而提高了系统的安全性。

(2)代理模式可以为被代理对象提供额外的功能,例如远程访问、缓存等,在不改变原有代码的情况下扩展了系统的功能。

(3)代理模式可以提高系统的性能,例如基于类的动态代理在运行时生成代理类,减少了编译时的性能开销。

缺点

(1)代理模式会增加系统的复杂度,需要编写额外的代码来实现代理对象。

(2)代理模式可能会降低系统的性能,例如基于接口的动态代理在运行时需要使用反射来调用被代理对象的方法,会带来一定的性能开销。

四、总结

本文介绍了 Java 中代理模式的实现方式和优缺点,并提供了相应的代码示例。在实际开发中,我们可以根据具体的需求选择适合的代理模式实现方式。静态代理适用于代理对象数量较少、代理类与被代理类的关系固定的情况,动态代理适用于代理对象数量较多、代理类与被代理类的关系不固定的情况。同时,我们也需要权衡代理模式的优缺点,选择最合适的方案来提高系统的可维护性和性能。


http://www.kler.cn/news/16803.html

相关文章:

  • ospf扩展配置—认证、沉默接口、加快收敛、缺省路由
  • 2023-04-23 学习记录--C/C++-邂逅C/C++(中)
  • hive 清空分区表 多姿势对比
  • 微服务知识2
  • C语言文件操作【基础知识 + 顺序读写 + 文件版通讯录】
  • 【Java笔试强训 17】
  • maven install的时候报Unable to find main class
  • 财报解读:照明行业景气上行,欧普照明已步入增长“快车道”
  • Noah-MP陆面过程模型建模方法与站点、区域模拟实践技术
  • linux命令之tar详解
  • 快速了解车联网V2X通信
  • 接踵而至,昆仑万维天工大语言模型发布
  • Linux必会100个命令(六十)curl
  • 小满nestjs(第二十八章 nestjs 事务)
  • 1.软件测试
  • 常见元件、封装、尺寸、表面处理等
  • C语言中的三种语句
  • fastai2 实现SSD
  • 1699_simulink代码生成配置初级方案
  • 【Java】内部类Object类
  • SpringBoot整合Redis实现点赞、收藏功能
  • @TransactionalEventListener的使用和实现原理
  • 【五一创作】【Simulink】采用延时补偿的三相并网逆变器FCS-MPC
  • 如何在CentOS上详细安装PageOffice进行企业文档管理和协作
  • Java 基础入门篇(五)—— 面向对象编程
  • 05_从0运行,重定位,初始化,中断再到定时器
  • kafka单机配置
  • 探索三维世界【3】:Three.js 的 Geometry 几何体 与 Material 材质
  • 《QDebug 2023年4月》
  • 烟火识别智能监测系统 yolov5