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

news2024/11/25 4:55:40

一、介绍

代理模式是一种常见的设计模式,它可以为其他对象提供一种代理以控制对这个对象的访问。代理对象具有与被代理对象相同的接口,客户端无需知道代理对象和被代理对象的区别。代理模式可以应用于各种不同的场景,例如远程代理、虚拟代理、保护代理等。本文将介绍 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.coloradmin.cn/o/478476.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Ubantu docker学习笔记(九)容器监控 自带的监控+sysdig+scope+cAdvisor+prometheus

文章目录 一、Docker命令监控二、Sysdig2.1介绍2.2 基本操作2.2.1 切换视图2.2.2 查看标签含义2.2.3 排序2.2.4 查看内部进程2.2.5 查找2.2.6 暂停2.2.7 上一级2.2.8 退出 三、Weave Scope3.1介绍3.2基本操作3.2.1 显示容器3.2.2 选择容器3.2.3 按照CPU使用情况排序3.2.4 控制容…

手动开发 简单的 Spring 基于 XML 配置的程序

目录 手动开发- 简单的 Spring 基于 XML 配置的程序 需求说明 思路分析 WyxApplicationContextTest xml配置 注意 手动开发- 简单的 Spring 基于 XML 配置的程序 需求说明 1. 自己写一个简单的 Spring 容器, 通过读取 beans.xml,获取第 1 个 JavaBean: Mon…

【建议收藏】Pandas(一)——初见Series

文章目录 📚引言📖库的安装以及一些说明📑库的安装📑一些说明 📖Series📑创建一个Series🔖从列表创建Series🔖从字典创建Series🔖标量创建Series 📑Series的特…

SpringSecurity认证原理和自定义认证

认证原理和自定义认证 认证配置表单认证注销登录前后端分离认证添加验证码 自定义认证 自定义资源权限规则 /index 公共资源/hello … 受保护资源 权限管理 在项目中添加如下配置就可以实现对资源权限规则设定: Configuration public class WebSecurityConfigurer extend…

node笔记_http服务搭建(渲染html、json)

文章目录 ⭐前言⭐初始化项目调整npm 的script运行入口搭建hello world的http服务npm run dev执行主函数的http服务 ⭐http返回类型html模板文件返回安装express渲染html的字符串 渲染html文件 sendFile渲染json返回数据类型 res.json ⭐结束 ⭐前言 大家好,我是ym…

CTF权威指南 笔记 -第二章二进制文件- 2.2 -ELF文件格式

目录 ELF的文件类型 ELF文件的结构 ELF文件头 节头表 代码节 数据节和只读数据节 bss节 字符串表 符号表 重定位 可执行文件的装载 常见的段 ELF就是可执行可连接格式 为linux运行文件格式 ELF的文件类型 我们使用复杂的例子进行演示 #include<stdio.h>int gl…

成功解决长时间挂起虚拟机后再次打开无法连接网络,并提示网络激活失败(亲测有效)

成功解决长时间挂起虚拟机后再次打开无法连接网络&#xff0c;并提示网络激活失败&#xff08;亲测有效&#xff01;&#xff09; 之前做区块链的一个虚拟机很久没打开&#xff0c;一直处于挂起状态&#xff0c;一直提示网络连接激活失败。试了很多种方法没解决&#xff0c;更…

人力资源管理系统有哪些推荐?

人力资源管理系统是现代企业管理中必不可少的工具&#xff0c;它可以帮助企业高效地管理人员的入职、离职、考勤、绩效、薪酬等方面的信息。 然而&#xff0c;市场上的HRM系统琳琅满目&#xff0c;选择一款合适的系统并不容易。 今天就来给大家介绍六款好用的人力资源管理系统…

自动化运维工具---Ansible Playbook语法实战(一)

目录 一、Ansible Playbook剧本初识 1.1 Ansible Playbook 基本概述 1.1.1 什么是playbook 1.1.2 Ansible playbook 与AD-Hoc的关系 1.2 Ansible Playbook 书写格式 1.2.1安装NFS 服务 1.3 Playbook变量详解 1.3.1 使用 vars定义变量 1.3.2 使用 vars_flies定义变量 …

中国平安将在2023年出现转机,复苏才刚刚开始

来源&#xff1a;猛兽财经 作者&#xff1a;猛兽财经 在解封后股价出现短暂反弹之后&#xff0c;由于市场担忧中国平安&#xff08;02318&#xff09;人寿保险部门新业务NBV&#xff08;用于衡量寿险公司新业务价值的一个重要指标,当一家保险公司的NBV指标越高,那么说明每新增…

码出高效:Java开发手册笔记(线程安全)

并发与并行的目标都是尽可能快地执行完所有任务。以医生坐诊为例&#xff0c;某个科室有两个专家同时出诊&#xff0c;这就是两个并行任务&#xff0c;其中一个医生&#xff0c;时而问诊&#xff0c;时而查看化验单&#xff0c;然后继续问诊&#xff0c;突然又中断去处理病人的…

总线、I/O总线、I/O接口

总线是计算机内数据传输的公共路径&#xff0c;用于实现两个或以上部件之间的信息交换。计算机系统中有多种总线&#xff0c;它们在各个层次上提供部件之间的连接和信息交换通路。 核内总线&#xff1a;在处理器核内部各元件之间连线的总线称为核内总线&#xff0c;可连接核内…

Java-数据结构-并查集<二>

一.并查集的简单介绍 二. 并查集的主要构成和实现方式 三.HashMap模板和数组模板 由于在下文的模板基本一致&#xff0c;不再每次都罗列&#xff0c;大体的模板如下&#xff0c;若有错误可以在leetcode找到对应的题目解答&#xff0c;已经附上连接。 HashMap class UnionFi…

本周大新闻|苹果首款MR没有主打卖点;Meta认为AI是AR OS的基础

​本周XR大新闻&#xff0c;AR方面&#xff0c;苹果首款MR或没有主打卖点&#xff0c;反而尽可能支持更多App和服务&#xff1b;扎克伯格表示基于AI的AR眼镜操作系统是下一代计算平台的基础&#xff1b;微软芯片工程VP Jean Boufarhat加入Meta芯片团队&#xff1b;Humane展示了…

[计算机图形学]高级光线传播与复杂外观建模(前瞻预习/复习回顾)

本篇不涉及技术细节* 一、高级光线传播* 1.有偏和无偏估计 无偏估计&#xff0c;比如我们在之前做路径追踪的时候&#xff0c;我们用许多样本去近似定积分的值&#xff0c;无论我们取的样本数量是多少&#xff0c;它的期望永远是对的&#xff0c;也就是我们真实的定积分的值&…

Python入门(一)Python概述与环境搭建

Python概述与环境搭建 1.概述1.1版本及下载1.2 Python 特点 2.环境搭建3.第一个程序“hello&#xff0c;world”4.可能会存在的问题 1.概述 Python 是一个高层次的结合了解释性、编译性、互动性和面向对象的脚本语言。 Python 的设计具有很强的可读性&#xff0c;相比其他语言…

【WAF】雷池waf升级体验

文章目录 前言一、更新二、功能体验1.仪表板2.自定义规则&#xff1a;3. 通用配置&#xff1a; 更新总结新增优化&#xff1a; 前言 最近雷池有比较大的更新&#xff0c;安装可以参考以前文章雷池waf安装&#xff0c;更新了数据统计也就是仪表板和自定义规则和通用配置还有IP高…

AI行为分析预警系统 opencv

AI行为分析预警系统通过pythonopencv网络模型Ai视觉智能分析技术&#xff0c;AI行为分析预警系统可以对实际场景下如车间、电力场景、化工场景、工业生产场景下的人员作业操作行为规范进行有针对性的定制开发&#xff0c;根据每个项目的不同的识别预警需求。OpenCV可以在不同的…

BEV(0)---Transformer

1 Transformer Transformer是一个Sequence to Sequence model&#xff0c;特别之处在于它大量用到了self-attention&#xff0c;替代了RNN&#xff0c;既考虑了Sequence的全局信息也解决了并行计算的问题。 1.1 self-attention&#xff1a; ①. 输入x1 ~ x4为一个sequence&…

Mysql-SQL优化

SQL优化 插入数据优化1&#xff09;批量插入数据2&#xff09;手动控制事务3&#xff09;主键顺序插入大批量插入数据 主键优化order by优化group by优化limit优化count优化update优化小结 插入数据优化 插入数据优化主要是对于insert进行批量插入时优化&#xff0c;下面我们就…