Java设计模式 11-代理模式

news2024/10/5 14:11:23

代理模式

一、 代理模式(Proxy)

1、代理模式的基本介绍

  1. 代理模式:为一个对象提供一个替身,以控制对这个对象的访问。即通过代理对象访问目标对象.这样做的好处是: 可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能
  2. 被代理的对象可以是远程对象创建开销大的对象需要安全控制的对象
  3. 代理模式有不同的形式, 主要有三种 静态代理、动态代理 (JDK 代理、接口代理)和 Cglib 代理 (可以在内存动态的创建对象,而不需要实现接口, 他是属于动态代理的范畴)

代理模式示意图

image-20210701203224584

二、静态代理

1、静态代码模式的基本介绍

静态代理在使用时,需要定义接口或者父类,被代理对象(即目标对象)与代理对象一起实现相同的接口或者是继承相同父类

2、应用实例

  • 具体要求

1)定义一个接口:ITeacherDao

2)目标对象 TeacherDAO 实现接口 ITeacherDAO

3)使用静态代理方式,就需要在代理对象 TeacherDAOProxy 中也实现 ITeacherDAO

4)调用的时候通过调用代理对象的方法来调用目标对象.

5)特别提醒:代理对象与目标对象要实现相同的接口,然后通过调用相同的方法来调用目标对象的方法

  • 思路分析图解(类图)

image-20210701205352092

  • 代码实现

主方法

public class Client {
    public static void main(String[] args) {
        //创建目标对象(被代理对象)
        TeacherDao teacherDao = new TeacherDao();

        //创建代理对象, 同时将被代理对象传递给代理对象
        TeacherDaoProxy teacherDaoProxy = new TeacherDaoProxy(teacherDao);

        //通过代理对象,调用到被代理对象的方法
        //即:执行的是代理对象的方法,代理对象再去调用目标对象的方法
        teacherDaoProxy.teach();
    }
}

ITeacherDao接口

//接口
public interface ITeacherDao {
    void teach(); // 授课的方法
}

TeacherDao类,被代理对象

public class TeacherDao implements ITeacherDao {
    @Override
    public void teach() {
        System.out.println(" 老师授课中	。。。。。");
    }
}

TeacherDaoProxy类,代理对象

//代理对象,静态代理
public class TeacherDaoProxy implements ITeacherDao{
    private ITeacherDao target; //被代理对象,聚合关系

    //构造器
    public TeacherDaoProxy(ITeacherDao target) { 
        this.target = target;
    }

    @Override
    public void teach() {
        System.out.println("开始代理	完成某些操作。。。。。 ");//方法target.teach();
        System.out.println("提交。。。。。");//方法
    }
}

15.1.1 静态代理优缺点

  • 1)优点
    • 不修改目标对象的功能前提下, 能通过代理对象对目标功能扩展
  • 2)缺点
    • 因为代理对象需要与目标对象实现一样的接口,所以会有很多代理类
  • 3)一旦接口增加方法,目标对象与代理对象都要维护

三、动态代理

15.1.1 动态代理模式的基本介绍

1)代理对象, 不需要实现接口,但是目标对象要实现接口,否则不能用动态代理

2)代理对象的生成,是利用 JDK 的 API,动态的在内存中构建代理对象

3)动态代理也叫做: JDK 代理、接口代理

2、JDK 中生成代理对象的 API

1)代理类所在包:java.lang.reflect.Proxy

2)JDK 实现代理只需要使用 newProxyInstance 方法,但是该方法需要接收三个参数,完整的写法是:

static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces,InvocationHandler h )

3、动态代理应用实例

  • 应用实例要求

将前面的静态代理改进成动态代理模式(即:JDK 代理模式)

  • 图解

image-20210701210805834

  • 代码实现

主函数

public class Client {
    public static void main(String[] args) {
        //创建目标对象,被代理类
        ITeacherDao target = new TeacherDao();

        //给目标对象,创建代理对象, 可以转成 ITeacherDao,获取代理类
        ITeacherDao proxyInstance = (ITeacherDao)new ProxyFactory(target).getProxyInstance();

        // proxyInstance=class com.sun.proxy.$Proxy0 内存中动态生成了代理对象
        System.out.println("proxyInstance=" + proxyInstance.getClass());
        
        //通过代理对象,调用目标对象的方法
        //proxyInstance.teach();
        proxyInstance.sayHello(" tom ");
    }
}

ITeacherDao

//接口
public interface ITeacherDao {
    void teach(); // 授课方法
    void sayHello(String name);
}

ProxyFactory

public class ProxyFactory {

    //维护一个目标对象 , Object 
    private Object target;

    //构造器 , 对 target  进行初始化
    public ProxyFactory(Object target) {
        this.target = target;
    }

    //给目标对象  生成一个代理对象
    public Object getProxyInstance() {
        //说明
        /*
        *	public static Object newProxyInstance(ClassLoader loader,
        Class<?>[] interfaces, InvocationHandler h)

        //1. ClassLoader loader : 指定当前目标对象使用的类加载器, 获取加载器的方法固定
        //2. Class<?>[] interfaces:  目标对象实现的接口类型,使用泛型方法确认类型
        //3. InvocationHandler h : 事情处理,执行目标对象的方法时,会触发事情处理器方法, 会把当前执行
        的目标对象方法作为参数传入
        */
        return Proxy.newProxyInstance(target.getClass().getClassLoader(),target.getClass().getInterfaces(),new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                System.out.println("JDK 代理开始~~");
                //反射机制调用目标对象的方法
                Object returnVal = method.invoke(target, args);
                System.out.println("JDK 代理提交"); 
                return returnVal;
            }
        });
    }
}

TeacherDao,被代理类

public class TeacherDao implements ITeacherDao {
    @Override
    public void teach() {
        System.out.println(" 老师授课中.... ");
    }
    
    @Override
    public void sayHello(String name) {
        System.out.println("hello " + name);
    }
}

四、 Cglib 代理

1、Cglib 代理模式的基本介绍

1)静态代理和 JDK 代理模式都要求目标对象是实现一个接口,但是有时候目标对象只是一个单独的对象,并没有实现任何的接口,这个时候可使用目标对象子类来实现代理-这就是 Cglib 代理

2)Cglib 代理也叫作子类代理,它是在内存中构建一个子类对象从而实现对目标对象功能扩展, 有些书也将Cglib 代理归属到动态代理。

3)Cglib 是一个强大的高性能的代码生成包,它可以在运行期扩展 java 类与实现 java 接口.它广泛的被许多 AOP 的框架使用,例如 Spring AOP,实现方法拦截

4)在 AOP 编程中如何选择代理模式:

  1. 目标对象需要实现接口,用 JDK 代理
  2. 目标对象不需要实现接口,用 Cglib 代理

5)Cglib 包的底层是通过使用字节码处理框架 ASM 来转换字节码并生成新的类

2、Cglib 代理模式实现步骤

1)需要引入 cglib 的 jar 文件

image-20210701213619560

2)在内存中动态构建子类,注意代理的类不能为 final,否则报错java.lang.IllegalArgumentException:

3)目标对象的方法如果为 final/static,那么就不会被拦截,即不会执行目标对象额外的业务方法.

3、 Cglib 代理模式应用实例

  • 应用实例要求

将前面的案例用 Cglib 代理模式实现

  • 思路图解

image-20210701215220914

  • 代码实现

主函数

public class Client {
    public static void main(String[] args) {
        //创建目标对象
        TeacherDao target = new TeacherDao();
        //获取到代理对象,并且将目标对象传递给代理对象
        TeacherDao proxyInstance = (TeacherDao)new ProxyFactory(target).getProxyInstance();

        //执行代理对象的方法,触发 intecept  方法,从而实现 对目标对象的调用
        String res = proxyInstance.teach();
        System.out.println("res=" + res);
    }
}

ProxyFactory代理类

public class ProxyFactory implements MethodInterceptor {
    //维护一个目标对象 ,聚合关系
    private Object target;

    //构造器,传入一个被代理的对象
    public ProxyFactory(Object target) {
        this.target = target;
    }

    //返回一个代理对象:	是 target 对象的被代理对象
    public Object getProxyInstance() {
        //1. 创建一个工具类
        Enhancer enhancer = new Enhancer();
        //2. 设置父类,传入被代理类的class类
        enhancer.setSuperclass(target.getClass());
        //3. 设置回调函数
        enhancer.setCallback(this);
        //4. 创建子类对象,即代理对象
        return enhancer.create();
    }
    
    //重写intercept()方法,会调用目标对象的方法
    @Override
    public Object intercept(Object arg0, Method method, Object[] args, MethodProxy arg3) throws Throwable {
        System.out.println("Cglib 代理模式 ~~ 开始"); 
        Object returnVal = method.invoke(target, args); 
        System.out.println("Cglib 代理模式 ~~ 提交"); 
        return returnVal;
    }
}

TeacherDao被代理类

public class TeacherDao {
    public String teach() {
        System.out.println(" 老师授课中	, 我是 cglib 代理,不需要实现接口 "); return "hello";
    }
}

五、几种常见的代理模式介绍— 几种变体

1)防火墙代理

内网通过代理穿透防火墙,实现对公网的访问。

2)缓存代理

比如:当请求图片文件等资源时,先到缓存代理取,如果取到资源则 ok,如果取不到资源,再到公网或者数据库取,然后缓存。

3)远程代理

远程对象的本地代表,通过它可以把远程对象当本地对象来调用。远程代理通过网络和真正的远程对象沟通信息。

4)同步代理

主要使用在多线程编程中,完成多线程间同步工作同步代理:主要使用在多线程编程中,完成多线程间同步工作

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/416628.html

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

相关文章

时间序列的平稳性

如何检查时间序列是否平稳&#xff0c;如果它是非平稳的&#xff0c;我们可以怎么处理 当未来的数据与现在相似时&#xff0c;它更容易建模。平稳性描述了时间序列的统计特征不随时间变化的概念。因此一些时间序列预测模型&#xff0c;如自回归模型&#xff0c;依赖于时间序列…

IoC 之 Spring 统一资源加载策略【Spring源码】

《JavaPub源码》 文末是系列文章 IoC 之 Spring 统一资源加载策略 Spring 框架的核心是 IoC&#xff08;Inversion of Control&#xff09;&#xff0c;它将应用程序的对象依赖关系管理和控制反转到容器中。在 Spring IoC 容器中&#xff0c;组件的创建和配置是通过外部配置…

IDEA 运行启动 pulsar-manager项目

IDEA 运行 pulsar-manager项目&#xff08;gradle&#xff09; 1、下载pulsar-manager源码 giithub地址 smn-manager 2、将项目导入IDEA并初始化项目 问题&#xff1a;SSL peer shut down incorrectly 将https改成http之后又会出现 Server returned HTTP response code: …

服务(第四篇)Apache的网页优化

一、网页压缩 ①首先检查是否安装 mod_deflate 模块 ②如果没有安装mod_deflate 模块&#xff0c;重新编译安装 Apache 添加 mod_deflate 模块 yum -y install gcc gcc-c pcre pcre-devel zlib-devel cd /opt/httpd-2.4.29/ ./configure \ --prefix/usr/local/httpd \ --enabl…

HDFS学习笔记 【Namenode/DN管理】

说明 DN管理管理了什么&#xff1f; NN上如何表示DN DN存储和块的关系 梳理DatanodeManager存储类 DatanodeDescriptor DN的抽象&#xff0c;依次继承。每一层增加一点额外的信息。 DatanodeId 基本的DN信息&#xff0c;hostname&#xff0c;数据传输接口&#xff0c;info服…

QTableView 设置selection-background-color和border不同时生效问题记录

问题&#xff1a; qtableview在使用过程种设置qss样式&#xff0c;设置选中时的背景色&#xff0c;以及边框颜色&#xff0c;不能同时生效。 解决&#xff1a; 在qss中设置QTableView的样式时&#xff0c;对于item项&#xff0c;selection-background-color的参数设置应该分…

在将公司“一拆六”后,阿里巴巴未来将释放出哪些投资价值?

来源&#xff1a;猛兽财经 作者&#xff1a;猛兽财经 阿里巴巴为何要将公司拆分为六大业务集团 3月28日&#xff0c;阿里巴巴集团董事会主席兼首席执行官张勇发布全员信&#xff0c;宣布启动“16N”组织变革&#xff0c;将公司拆分为六大业务集团和多家业务分公司。 在阿里巴巴…

关于FPGA(Vivado)后仿真相关问题的探讨

FPGA后仿真时&#xff0c;相比于功能仿真增加了门延时和布线延时&#xff0c;相对于门级仿真增加了布线延时&#xff0c;因此后仿真相比于功能仿真具有不同的特点。 下面所示的代码在功能仿真时是正确的的&#xff0c;但在后仿真时&#xff0c;似乎是有问题的。功能很简…

大数据项目组-月度考核汇报0102

目录 01-2023年02月-月度考核汇报 2月份完成项目情况 2月份学习情况 3月份学习计划 老师点评 02-2023年03月-月度考核汇报 项目完成情况 本月学习内容 下月学习计划 老师点评 01-2023年02月-月度考核汇报 2月份完成项目情况 MySQL数据同步到ElasticSearch任务进展&a…

linux shell 操作二进制文件(xxd、dd)

1&#xff0c;生成一个二进制文件 dd 工具 # 全零 二进制文件 dd if/dev/zero of1.bin bs1 count1024#全0xff tr \000 \377 < /dev/zero | dd ofall_0xff.bin bs1 count1024 > /dev/null xxd 工具&#xff1a;只能改单个地址 # echo "0x123" | xxd -r – xx…

【华为od2023-C++版】字符串重新排列、字符串重新排序

华为od机试题C2023个人练习使用 字符串重新排列、字符串重新排序 题目描述 给定一个字符串s&#xff0c;s包括以空格分隔的若干个单词&#xff0c;请对s进行如下处理后输出:1、单词内部调整:对每个单词字母重新按字典序排序Q 2、单词间顺序调整: 1)统计每个单词出现的次数&a…

算法刷题日志

今天是星期几就加上多少天在最后 public class Main {public static void main(String[] args) {System.out.println(Math.pow(20, 22) % 7 6);} }这题是判断左右回文&#xff0c;且要保持单调性&#xff0c;因为回文数左右对称所以只需要判断左边是否单调递增。 public class…

模拟信号隔离放大器变送器 导轨安装DIN11 IPO EM系列

概述&#xff1a; 导轨安装DIN11 IPO EM系列模拟信号隔离放大器是一种将输入信号隔离放大、转换成按比例输出的直流信号混合集成电路。产品广泛应用在电力、远程监控、仪器仪表、医疗设备、工业自控等需要电量隔离测控的行业。该模块内部嵌入了一个高效微功率的电源&#xff0…

yolov5详解与改进

https://github.com/z1069614715/objectdetection_script YOLOV5改进-Optimal Transport Assignment Optimal Transport Assignment&#xff08;OTA&#xff09;是YOLOv5中的一个改进&#xff0c;它是一种更优的目标检测框架&#xff0c;可以在保证检测精度的同时&#xff0c…

研究的艺术 (The craft of research) 读书笔记

前言 如果你对这篇文章感兴趣&#xff0c;可以点击「【访客必读 - 指引页】一文囊括主页内所有高质量博客」&#xff0c;查看完整博客分类与对应链接。 对于研究者而言&#xff0c;写作是一件很重要的事&#xff0c;好的写作不仅能让更多人愿意读&#xff0c;获得更大影响力&…

k8s学习-CKS真题-K8S安全策略PodSecurityPolicy

目录题目环境搭建解题参考题目 Task 使用 Trivy 开源容器扫描器检测 namespace kamino 中 Pod 使用的具有严重漏洞的镜像。 查找具有 High 或 Critical 严重性漏洞的镜像&#xff0c;并删除使用这些镜像的 Pod。 注意&#xff1a;Trivy 仅安装在 cluster 的 master 节点上&…

开源的全文搜索引擎总结,chatbot和chatgpt项目必备资源

全文搜索引擎就是通过从互联网上提取的各个网站的信息&#xff08;以网页文字为主&#xff09;而建立的数据库中&#xff0c;检索与用户查询条件匹配的相关记录&#xff0c;然后按一定的排列顺序将结果返回给用户。 1、Apache Lucene Java 全文搜索框架 许可证&#xff1a;Apa…

中文英文翻译-英翻中文在线翻译

如果您需要将大量的英文文件或网页翻译成中文&#xff0c;那么我们的批量翻译英文翻译中文的软件将是您最佳的选择。我们的软件是一款高效、准确、节省时间的翻译工具&#xff0c;可以在最短时间内完成大量英文文本的翻译&#xff0c;让您在工作生活中处处流畅地处理英语文本。…

【云原生进阶之容器】第六章容器网络6.4.3--Flannel网络模式

《云原生进阶之容器》专题索引: 第一章Docker核心技术1.1节——Docker综述第一章Docker核心技术1.2节——Linux容器LXC第一章Docker核心技术1.3节——命名空间Namespace第一章Docker核心技术1.4节——chroot技术第一章Docker核心技术1.5.1节——cgroup综述

算法套路八——二叉树深度优先遍历(前、中、后序遍历)

算法套路八——二叉树深度优先遍历&#xff08;前、中、后序遍历&#xff09; 算法示例&#xff1a;LeetCode98&#xff1a;验证二叉搜索树 给你一个二叉树的根节点 root &#xff0c;判断其是否是一个有效的二叉搜索树。 有效 二叉搜索树定义如下&#xff1a; 节点的左子树只…