静态代理和动态代理

news/2024/9/22 20:57:24/

目录

一、什么是代理模式

二、静态代理

1.定义

2.实现

三、动态代理

1 定义

2 实现

四、静态代理与动态代理

五、总结


一、什么是代理模式

        代理模式是一种设计模式,它允许一个对象访问另外一个对象。代理对象通常通过包含真实对象的引用来控制对真实对象的操作。代理模式分为静态代理和动态代理两种。

二、静态代理

1.定义

        静态代理是在编译时期就确定的代理类。代理类与目标类实现相同的接口。代理类手动编写,代理类作用是调用目标类的方法,同时可以在方法调用前后加入一些操作。

2.实现

2.1 先定义一个UserService的接口,其中包含两个方法select()和update()。

public interface UserService {public void select();public void update();
}

2.2 UesrService接口的具体实现类:UserServiceImpl。

        这是真实主题(真正的业务类):

//RealSubject 真实主题(真正的业务类)
public class UserServiceImpl implements UserService{@Overridepublic void select() {System.out.println("查询selectById");}@Overridepublic void update() {System.out.println("更新update");}}

 2.3 定义了一个名为UserServiceProxy 的静态代理类。

//代理
public class UserServiceProxy implements UserService{//包含Subject真实的主题private UserServiceImpl realUserService = new UserServiceImpl();@Overridepublic void select() {long begin = System.currentTimeMillis();//调用真正的业务逻辑realUserService.select();long end = System.currentTimeMillis();System.out.println("select()执行耗时"+(end-begin)+"毫秒");}@Overridepublic void update() {realUserService.update();}

        这个代理类实现了UserService接口,并包含了一个UserServiceImpl 对象来执行实际的业务逻辑。在代理类中,可以在调用真实业务逻辑之前或之后添加额外的操作。

2.4 静态代理的优缺点:

优点:

  • 编译期检查,容易发现问题。
  • 代码清晰易读,易于维护。

缺点

  • 不灵活,修改或扩展目标类需要同时修改代理类。
  • 存在大量的重复代码。

三、动态代理

1 定义

        动态代理是在运行时生成代理类的。与静态代理不同,动态代理不需要手动编写代理类,而是使用Java的反射机制动态生成代理类。

2 实现

2.1 先定义一个OrderService 接口。

public interface OrderService {public void create(int money,int uid);}

2.2  OrderService接口的具体实现类:OrderServiceImpl 。

public class OrderServiceImpl implements OrderService{@Overridepublic void create(int money, int uid) {System.out.println("订单被创建");}
}

 2.3 定义了一个 PerformanceInvocationHandler 类。

//用于检测方法执行性能的Handler执行器
public class PerformanceInvocationHandler implements InvocationHandler{private Object real;public PerformanceInvocationHandler(Object real) {this.real = real;}/*** 参数proxy: 代理对象* 参数method:当前执行的方法对象* 参数args:参数列表* */@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {long begin = System.currentTimeMillis();//真实业务对象当前的执行方法(基于反射的方式)Object returnValue = method.invoke(real, args);long end = System.currentTimeMillis();System.out.println("方法执行耗时"+(end - begin)+"毫秒!");return returnValue;}
}

         PerformanceInvocationHandler类实现了InvocationHandler接口,用于动态代理模式中监控方法的执行性能。

        invoke方法:该方法的作用是在方法调用前后添加额外的功能,例如计算方法的执行时间。

        在 invoke 方法中,使用反射机制调用真实业务对象的目标方法 method.invoke(real, args),并记录执行时间。最后,将执行耗时打印出来。

2.4 使用 Java 动态代理来为OrderServiceImpl 类生成代理对象,并在方法调用前后进行性能监控。

public class Text01 {public static void main(String[] args) {//真实的主题对象OrderServiceImpl realOrderService = new OrderServiceImpl();//获取类加载器ClassLoader classLoader = realOrderService.getClass().getClassLoader();//接口列表Class[] interfaces = realOrderService.getClass().getInterfaces();//创建InvocationHandler对象(动态代理对象的执行逻辑)PerformanceInvocationHandler h = new PerformanceInvocationHandler(realOrderService);//创建一个代理对象(动态代理对象)OrderService orderServiceProxy = (OrderService) Proxy.newProxyInstance(classLoader, interfaces, h);//调用方法orderServiceProxy.create(1234, 0001);	}
}

        使用Proxy.newProxyInstance方法创建代理对象。这个代理对象会实现OrderService接口,

并在调用方法时使用PerformanceInvocationHandler 中的invoke方法来处理。

四、静态代理与动态代理

对比维度静态代理动态代理
实现方式代理类在编译期确定代理类在运行时动态生成
代理类的数量每个目标类对应一个代理类一个代理类可以代理多个目标类
编写难度需要手动编写代理类,重复代码多只需编写一个InvocationHandler实现类
性能性能较高,不涉及反射性能较低,依赖反射机制
灵活性不灵活,目标类变化时代理类需同步修改灵活,目标类变化时无需修改代理类

五、总结

  • 静态代理适用于结构简单、需求明确的场景,如对固定业务逻辑的增强。
  • 动态代理适用于复杂、需求变化频繁的场景,特别是在AOP(面向切面编程)中应用广泛。

http://www.ppmy.cn/news/1523823.html

相关文章

Mysql基础练习题 1757.可回收且低脂的产品(力扣)

编写解决方案找出既是低脂又是可回收的产品编号。 题目链接: https://leetcode.cn/problems/recyclable-and-low-fat-products/description/ 建表插入数据: Create table If Not Exists Products (product_id int, low_fats ENUM(Y, N), recyclable …

hive表格统计信息不准确

问题描述 有个hive分区表,orc存储格式,有个分区,查询 select count(1) from table where dtyyyyMMdd 结果是0, 但查询 select * from table where dtyyyyMMdd又能查到数据,去hdfs对应目录下查看,也能看到有…

【JavaEE初阶】多线程(1)

欢迎关注个人主页:逸狼 创造不易,可以点点赞吗~ 如有错误,欢迎指出~ 目录 并发编程 线程 与 进程 创建线程 写法1 写法2 写法3 写法4 写法5 Thread类的常见构造方法 前台/后台 线程 并发编程 并发编程: 通过写特殊的代码 把多个cpu的核心…

Java——踩坑Arrays.asList()

坑1:不能直接使用 Arrsys.asList() 来转换基本类型数据 public static void test1(){// 1、不能直接使用asList来转换基本类型数组int[] arr {1, 2, 3};List list Arrays.asList(arr);System.out.printf("list:%s size:%s class:%s", list, list.size(…

理解 RabbitMQ:生产者、连接、通道、交换机、队列与消费者的消息流

在分布式消息系统中,RabbitMQ 是一个非常流行的消息代理。它的核心理念是解耦应用程序的生产者和消费者,使得消息能够可靠地从一方传递到另一方。本文将带你深入了解 RabbitMQ 中 生产者、连接、通道、交换机、队列 和 消费者 之间的消息流,并…

Agent探索之OpenAI方式调用本地模型(one-api)

介绍 https://github.com/songquanpeng/one-api OpenAI 接口管理 & 分发系统,支持 Azure、Anthropic Claude、Google PaLM 2 & Gemini、智谱 ChatGLM、百度文心一言、讯飞星火认知、阿里通义千问、360 智脑以及腾讯混元,可用于二次分发管理 key&…

0910作业+思维导图

一、作业(实现一个闹钟) 1、代码 #include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this);//调整标签页大小this->resize(800,400);//lab:显示系统时间…

《C++》解密--算法复杂度

要正式开通C博客之路啦!! 一、数据结构 1、数据结构定义 数据结构 是计算机存储、组织数据的方式,指相互之间存在一种或多种特定关系的数据元 素的集合。 2、算法定义 算法 就是定义良好的计算过程,他取一个或一组的值为…