代理模式---静态代理和动态代理

news/2024/9/19 8:43:41 标签: 代理模式, java

代理模式

        代理模式给某一个对象提供一个代理,并由代理对象来控制对真实对象的访问。代理模式是一种结构型设计模式

        代理模式角色分为 3 种:

Subject(抽象主题角色):定义代理类和真实主题的公共对外方法,通常被设计成接口;

RealSubject(真实主题角色):真正实现业务逻辑的类;

Proxy(代理主题角色):用来代理和封装真实主题;

        代理模式的结构比较简单,其核心是代理类,为了让客户端能够一致性地对待真实对象和代理对象,在代理模式中引入了抽象层。

         如果根据字节码的创建时机来分类,可以分为静态代理动态代理

静态代理

        所谓静态也就是在程序运行前就已经存在代理类的字节码文件,代理类和真实主题角色的关系在运行前就确定了

        假设有UserService接口及其实现类UserServiceImpl,我们需要在不改变实现类代码的基础上,增加日志记录的功能。

//Subject

java">public interface UserService {
	public void select();
	public void update();

}

//RealSubject 真实主题对象(真正的业务类)

java">public class UserServiceImpl implements UserService{	
	public void select() {
		System.out.println("查询selectById");		
	}	
	public void update() {
		System.out.println("更新updateById");
		
	}
}

//Proxy 代理对象

java">public class UserServiceProxy implements UserService{
	//创建真正的主题对象
    private UserServiceImpl realUserService=new UserServiceImpl ();

    @Override
	public void select() {
        long begin=System.currentTimeMillis();
        realUserService.select();
        long end=System.currentTimeMillis();
		System.out.println("select的执行时间为:"+(end-begin)+"毫秒");

    }
    @Override
	public void update() {
		// TODO Auto-generated method stub
		long begin=System.currentTimeMillis();
		realUserService.update();
		long end=System.currentTimeMillis();
		System.out.println("update的执行时间为:"+(end-begin)+"毫秒");
	}
}

//Test测试类

java">public class Test {
	public static void main(String[] args) {
        //创建代理对象
        UserServiceProxy proxy=new UserServiceProxy();
        proxy.select();
		proxy.update();
    }
}

//运行结果:

查询selectById
select的执行时间为:0毫秒
更新updateById
update的执行时间为:0毫秒

        通过静态代理,我们可以达成增强功能而不污染原代码,这是静态代理的优点。但是在一些场景复杂的时候,静态代理的缺点也会暴露出来:

1、 当需要代理多个类的时候,由于代理对象要实现与目标对象一致的接口,有两种方式

只维护一个代理类,由这个代理类实现多个接口,但是这样就导致代理类过于庞大,导致代码可读性差。

新建多个代理类,每个目标对象对应一个代理类,但是这样会产生过多的代理类,难以管理。

2、 当接口需要增加、删除、修改方法的时候,目标对象与代理类都要同时修改,不易维护

动态代理

        Java中两种常见的动态代理方式:JDK原生动态代理CGLIB动态代理(第三方开源类库)。

JDK动态代理

        JDK动态代理主要涉及两个类:java.lang.reflect.Proxy 和java.lang.reflect.InvocationHandler。我们通过编写一个调用逻辑处理器 LogHandler 类案例来提供日志增强功能,并实现 InvocationHandler 接口;在 LogHandler 中维护一个目标对象,这个对象是被代理的对象(真实主题角色);在 invoke()方法中编写方法调用的逻辑处理。

//准备好两个真实主题对象及其接口:

//1.UserService和UserServiceImp

java">public interface UserService {
	public void select();
	public void update();

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

//2.OrderService 和OrderServiceImp

java">public interface OrderService {
	public void creat(int money,int uid);

}
java">public class OrderServiceImpl implements OrderService{
	@Override
	public void creat(int money, int uid) {
		System.out.printf("商品%d的价格是:%d",uid,money);
		System.out.println();
	}

}

//InvocationHandler 接口的实现类

java">//用于检测方法运行时间的Handler执行器
public class PerformanceInvocationHandler implements InvocationHandler{
    private Object real;
	public PerformanceInvocationHandler(Object real) {
		this.real=real;
	}

    @Override
	public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //开始时间
		long begin=System.currentTimeMillis();
		
		//真实业务对象当前的执行方法(基于反射)
        //相当于调用了creat()、select()或update()方法
        //传入的真实主题对象是谁,就调用谁的方法
		Object returnValue=method.invoke(real, args);
		
        //结束时间
		long end=System.currentTimeMillis();
		
		System.out.println("方法耗时:"+(end-begin)+"毫秒");
		
		return returnValue;
	}

}

//实现OrderService代理的测试类

java">public class Test01 {
	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.creat(1234, 1);
	
	}

}

//运行结果:

商品1的价格是:1234
方法耗时:33毫秒

//实现UserService代理的测试类

java">public class Test02 {
	public static void main(String[] args) {
		//创建真实主题对象
		UserServiceImpl realUserService=new UserServiceImpl();
		
		//获取类加载器
		ClassLoader loader=realUserService.getClass().getClassLoader();
		
		//获取接口列表
		Class[] interfaces=realUserService.getClass().getInterfaces();
		
		//Handler
		PerformanceInvocationHandler h=new PerformanceInvocationHandler(realUserService);
		
		//创建动态代理对象
		UserService userServiceProxy=(UserService)Proxy.newProxyInstance(loader, interfaces, h);
		
		//调用方法
		userServiceProxy.update();
	}

}

 //运行结果:

更新updateById
方法耗时:0毫秒

        通过动态代理,我们不再需要创建不同代理类来实现不同的逻辑方法。动态代理是通过Proxy创建代理对象,然后将接口方法“代理”给InvocationHandler完成的。


http://www.niftyadmin.cn/n/5665276.html

相关文章

2024短剧系统开发,付费短剧小程序app源码教程,分销功能讲解搭建上线

短剧系统技术栈 前端:vue3uniapp 后端: php 数据库:mysql 服务器环境: centos7.6 宝塔 php7.4 MySQL5.7 一、短剧系统功能 短剧用户端: 小程序、抖音小程序、快手小程序、APP、 z付宝小程序 系统用户端详细功能&…

基于SpringBoot+定时任务实现地图上绘制车辆实时运动轨迹图

目录 1. 项目结构 2. Maven依赖配置 (pom.xml) 3. 实现后端服务 4. 配置文件 (application.properties) 5. 启动项目 6. 访问页面 实现基于北斗卫星的车辆定位和轨迹图的Maven工程(使用模拟数据),我们将使用以下技术: Spri…

【机器学习】任务五:葡萄酒和鸢尾花数据集分类任务

目录 1.实验基础知识 1.1 集成学习 (1)随机森林 (2)梯度提升决策树(GBDT) (3)XGBoost (4)LightGBM 1.2 参数优化 (1)网格搜索…

Docker Registry API best practice 【Docker Registry API 最佳实践】

文章目录 1. 安装 docker2. 配置 docker4. 配置域名解析5. 部署 registry6. Registry API 管理7. 批量清理镜像8. 其他 👋 这篇文章内容:实现shell 脚本批量清理docker registry的镜像。 🔔:你可以在这里阅读:https:/…

python学习笔记目录

基于windows下docker安装HDDM-CSDN博客 在python中安装HDDM-CSDN博客(这个办法没安装成功)

IDEA去除掉虚线,波浪线,和下划线实线的方法

初次安装使用IDEA,总是能看到导入代码后,出现很多的波浪线,下划线和虚线,这是IDEA给我们的一些提示和警告,但是有时候我们并不需要,反而会让人看着很不爽,这里简单记录一下自己的调整方法&#…

图书馆座位预约系统小程序的设计

管理员账户功能包括:系统首页,个人中心,用户管理,图书馆管理,座位信息管理,预约选座管理,签到信息管理,系统管理 微信端账号功能包括:系统首页,论坛&#xf…

Ansys Zemax | 如何使用琼斯矩阵表面

附件下载 联系工作人员获取附件 概览 琼斯矩阵 (Jones Matrix) 表面是一种非常简便的定义偏振元件的方法。这篇文章通过几个示例介绍了如何使用琼斯矩阵。 介绍 光线追迹程序一般只考虑光线的几何属性(位置、方向和相位)。光线传播到一个表面时的全…