温故知新之:代理模式,静态代理和动态代理(JDK动态代理)
0、前言
代理模式可以在不修改被代理对象的基础上,通过扩展代理类,进行一些功能的附加与增强。
1、静态代理
静态代理是一种代理模式的实现方式,它在编译期间就已经确定了代理对象,需要为每一个被代理对象创建一个代理类。静态代理的实现比较简单,但是每个被代理对象都需要创建一个代理类,因此在代理对象比较多时,会导致代码几余和维护成本增加。
静态代理有两种实现,继承和聚合两种模式。
1.1、继承模式
需要定义接口或者父类,被代理对象与代理对象一起实现相同的接口或者继续相同父类,代理对象继承目标对象,重新目标对象的方法。
目标对象:
package proxy.staticproxy.extends_model;//目标对象
public class UserService {public void login(){System.out.println("login success");}
}
代理类:
package proxy.staticproxy.extends_model;//代理对象
public class UserServiceProxy extends UserService{public void login(){System.out.println("开始执行--------------");super.login();}
}
测试类:
package proxy.staticproxy;import proxy.staticproxy.extends_model.UserServiceProxy;
import proxy.staticproxy.implements_model.FactoryOne;
import proxy.staticproxy.implements_model.FactoryOneProxy;
import proxy.staticproxy.implements_model.IFactory;public class Test {@org.junit.Testpublic void extends_model(){UserServiceProxy proxy = new UserServiceProxy();proxy.login();}// 待代理类来处理/// 场景:当不想改动被代理类的业务逻辑,在处理开始和结束分别加上时间显示/// 处理核心逻辑:需要实现被代理类的接口及方法,在实现方法中田间需要添加的业务处理逻辑@org.junit.Testpublic void implements_model(){// 创建被代理类的对象IFactory word = new FactoryOne();// 创建代理类的对象IFactory proxyPaperFactory = new FactoryOneProxy(word);proxyPaperFactory.production();}// 直接调用被代理类业务处理@org.junit.Testpublic void test01(){// 创建被代理类的对象IFactory word = new FactoryOne();word.production();}
}
执行结果:
开始执行--------------
login success
1.2、聚合模式
Subject:抽象主题角色,抽象主题类可以是抽象类,也可以是接口,是一个最普通的业务类型定义,无特殊要求。
RealSubject:具体主题角色,也叫被委托角色、被代理角色。是业务逻辑的具体执行者。
Proxy:代理主题角色,也叫委托类、代理类。它把所有抽象主题类定义的方法给具体主题角色实现,并且在具体主题角色处理完毕前后做预处理和善后工作。
Subject 接口:
package proxy.staticproxy.implements_model;public interface IFactory {void production();
}
RealSubject 类:
package proxy.staticproxy.implements_model;public class FactoryOne implements IFactory {@Overridepublic void production() {System.out.println(" 被代理类,开始初始化 ");System.out.println(" 生产笔记本、鼠标、键盘等等 ");System.out.println(" 被代理类处理完成 ");}
}
Proxy 类:
package proxy.staticproxy.implements_model;public class FactoryOneProxy implements IFactory {private IFactory factory; // 用被代理类对象进行实例化public FactoryOneProxy(IFactory factory) {this.factory = factory;}@Overridepublic void production() {System.out.println(" 代理开始工作 ,在此可以添加处理逻辑");factory.production();System.out.println(" 代理结束工作 ,在此可以添加处理逻辑");}
}
测试类:
package proxy.staticproxy;import proxy.staticproxy.extends_model.UserServiceProxy;
import proxy.staticproxy.implements_model.FactoryOne;
import proxy.staticproxy.implements_model.FactoryOneProxy;
import proxy.staticproxy.implements_model.IFactory;public class Test {@org.junit.Testpublic void extends_model(){UserServiceProxy proxy = new UserServiceProxy();proxy.login();}// 待代理类来处理/// 场景:当不想改动被代理类的业务逻辑,在处理开始和结束分别加上时间显示/// 处理核心逻辑:需要实现被代理类的接口及方法,在实现方法中田间需要添加的业务处理逻辑@org.junit.Testpublic void implements_model(){// 创建被代理类的对象IFactory word = new FactoryOne();// 创建代理类的对象IFactory proxyPaperFactory = new FactoryOneProxy(word);proxyPaperFactory.production();}// 直接调用被代理类业务处理@org.junit.Testpublic void test01(){// 创建被代理类的对象IFactory word = new FactoryOne();word.production();}
}
运行结果:
代理开始工作 ,在此可以添加处理逻辑被代理类,开始初始化 生产笔记本、鼠标、键盘等等 被代理类处理完成 代理结束工作 ,在此可以添加处理逻辑
2、动态代理
动态代理是一种代理模式的实现方式,它在运行期间根据需要动态生成代理对象,无需手动编写代理类,可以减少代码几余和维护成本。动态代理适用于需要代理的对象数量较多,代理类实现对灵活的场景,例Spring框架中的Spring AOP(面向切面编程)功能。
动态代理的实现方式也有两种,JDK动态代理和CGLB动态代理两种模式。本文重点介绍JDK动态代理,
在JDK中,有一个Proxy类(名词,代理人)。Proxy类是专门完成代理的操作类,可以通过此类为一个或多个接口动态的生成实现类。Proxy类提供的有一个静态方法:newProxyInstance()方法给我们的目标对象(委托对象)返回一个代理对象。
核心方法:newProxyInstance方法的三个参数,按照顺序分别是 ClassLoader (类加载器),interfaces(一组接口,接口数组),InvocationHandler(调用处理器)。
ClassLoader (类加载器)
定义了由哪个classLoader对象来对生成的代理对象进行加载。
接口数组:
一个Interface对象的数组,表示将要给我需要代理的对象提供一组什么接口,如果我提供了一组接口给它,那么这个代理对象就宣称实现了该接口(多态),这样我就能调用这组接口中的方法了。
调用处理器:
一个InvocationHandler接口,表示代理实例的调用处理程序实现的接口。每个代理实例都具有一个关联的调用处理程席。对代理实例调用方法时,将对方法调用进行编码并将其指派到它的调用处理程序的 invoke 方法(传入InvocationHandler接口的子类)。
对象接口:
package proxy.dynamicproxy.v3;public interface IAnimal {public void run();public void eat();public void sleep();
}
被代理类<Cat>:
package proxy.dynamicproxy.v3;public class Cat implements IAnimal{@Overridepublic void run() {System.out.println("Cat Run invoking!!!");}@Overridepublic void eat() {System.out.println("Cat eat invoking!!!");}@Overridepublic void sleep() {System.out.println("Cat sleep invoking!!!");}
}
被代理类<Dog>:
package proxy.dynamicproxy.v3;public class Dog implements IAnimal{@Overridepublic void run() {System.out.println("Dog Run invoking!!!");}@Overridepublic void eat() {System.out.println("Dog eat invoking!!!");}@Overridepublic void sleep() {System.out.println("Dog sleep invoking!!!");}
}
代理类工具类:
package proxy.dynamicproxy.v3;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;public class ProxyUtils {public Object object;public ProxyUtils(Object object) {this.object = object;}public Object createProxyObj(){// 动态代理 顾名思义 针对接口动态生成代理类处理业务逻辑// 返回动态代理/*ClassLoader loader, 要实现接口的类加载器Class<?>[] interfaces,接口类InvocationHandler h 处理类* **/ClassLoader loader = object.getClass().getClassLoader();
// Class<?>[] interfaces = new Class[]{argObj.getClass()}; // 当是接口Class<?>[] interfaces = object.getClass().getInterfaces(); // 当是类直接获取对应的接口方法;InvocationHandler handler = new IFactoryInvocationHandler();Object object = Proxy.newProxyInstance(loader, interfaces, handler);return object;}public class IFactoryInvocationHandler implements InvocationHandler {@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {System.out.println("IFactoryInvocationHandler invoke Before!!!");Object rtn = method.invoke(object, args);System.out.println("IFactoryInvocationHandler invoke After!!!");return rtn;}}}
测试类:
package proxy.dynamicproxy;import proxy.dynamicproxy.v3.Cat;
import proxy.dynamicproxy.v3.IAnimal;
import proxy.dynamicproxy.v3.ProxyUtils;public class Test {@org.junit.Testpublic void v3_common_test() {// 实例化代理工具类ProxyUtils proxyUtils = new ProxyUtils(new Cat());// 创建代理对象IAnimal animal = (IAnimal)proxyUtils.createProxyObj();// 调用被代理类的方法animal.eat();System.out.println("========================================================");animal.run();System.out.println("========================================================");animal.sleep();System.out.println("========================================================");}
}
运行结果:
IFactoryInvocationHandler invoke Before!!!
Cat eat invoking!!!
IFactoryInvocationHandler invoke After!!!
========================================================
IFactoryInvocationHandler invoke Before!!!
Cat Run invoking!!!
IFactoryInvocationHandler invoke After!!!
========================================================
IFactoryInvocationHandler invoke Before!!!
Cat sleep invoking!!!
IFactoryInvocationHandler invoke After!!!
========================================================Process finished with exit code 0
3、动态代理原理
JDK动态代理是一种实现代理模式的方式。它利用Java的反射机制,在运行时动态地创建代理对象,实现对目标对象的代理。
JDK动态代理的原理如下:
定义接口:首先需要定义一个接口,用于描述目标对象和代理对象的共同行为。
实现InvocationHandler接口:创建一个实现InvocationHandler接口的代理处理器类,该类负责对目标对象的方法进行代理。
获取代理类:通过java.lang.reflect.Proxy的静态方法newProxyInstance()创建代理类,该方法需要传入ClassLoader、接口数组和InvocationHandler实例。
调用代理对象:通过代理对象调用方法时,实际上是调用InvocationHandler的invoke()方法。
在invoke()方法中,可以进行一些额外的操作,比如在调用目标方法之前进行预处理、在调用目标方法后进行后处理等。
4、总结
相关文章:

温故知新之:代理模式,静态代理和动态代理(JDK动态代理)
0、前言 代理模式可以在不修改被代理对象的基础上,通过扩展代理类,进行一些功能的附加与增强。 1、静态代理 静态代理是一种代理模式的实现方式,它在编译期间就已经确定了代理对象,需要为每一个被代理对象创建一个代理类。静态代…...

软件工程(十二) 设计模式之创建型模式
我们传统的23种设置模式如下 创建型模式:用于创建对象 工厂方法(Factory Method) 模式抽象工厂(Abstract Factory) 模式原型(Protptype) 模式单例(Singleton) 模式构建器模式结构型模式:建立更大的结构 适配器(Adapter)模式桥接(Bridge)模式组合(Composite)模式装饰(D…...

使用docker、docker-compose部署微服务
使用docker、docker-compose部署微服务 一、使用docker部署1、准备2、上传jar包3、编写dockerfile文件3、构建镜像和容器 二、使用docker-compose部署1、准备服务的jar包和dockerfile文件2、编写docker-compose.yml文件3、docker-compose常用命令(1)、前…...

【Axure高保真原型】中继器网格图片拖动摆放
今天和大家分享中继器网格图片拖动摆放的原型模板,我们可以通过鼠标拖动来移动图片,拖动过程其他图标会根据图片拖动自动排列,松开鼠标是图片停放在指定位置,其他图标自动排列。那这个模板是用中继器制作的,所以使用也…...

《基于 Vue 组件库 的 Webpack5 配置》4. 压缩 CSS 和 js 文件
压缩 CSS 使用 webpack 插件 css-minimizer-webpack-plugin,需要额外安装 npm i css-minimizer-webpack-pluginlatest -D;压缩 js 使用 webpack 自带插件 terser-webpack-plugin,无需额外安装;package.json 的配置如下 const Css…...

electron globalShortcut 快捷键,在焦点移到其他软件上时,调用快捷键报错
用 electron 开发软件,在设置了 globalShortcut 快捷键后,在当前开发的软件上调用快捷键正常,但是当焦点不在当前软件时,在使用快捷键,好些时候会报错。大概率与系统快捷键产生冲突或者快键键控制的回调里获取的内容&a…...

【PHP】PHP条件控制
在PHP中,条件控制语句用于根据条件来执行不同的代码块。以下是一些常见的条件控制语句: if语句: if ($condition) {// 如果条件为真,执行此代码块 }if-else语句: if ($condition) {// 如果条件为真,执行…...

超干货!Linux中断响应流程
为了提高外部事件处理的实时性,现在的处理器几乎无一例外都含有中断控制器,外设也大都带有中断触发的功能。为了能支持这一特性,Linux系统中设计了一个中断子系统来管理系统中的中断。 那么你知道Linux系统中的中断响应是怎样的流程吗&#…...

统计学补充概念-13-逻辑回归
概念 逻辑回归(Logistic Regression)实际上是一种用于解决分类问题的统计学习方法,尽管其名称中带有"回归"一词,但它主要用于处理分类任务。逻辑回归用于预测一个事件发生的概率,并将其映射到一个特定的输出…...

java八股文面试[多线程]——什么是线程安全
对线程安全的理解 总结:一个进程内的多个线程同时访问堆内存。 知识来源: 【并发与线程】对线程安全的理解_哔哩哔哩_bilibili...

Redis 介绍
一.Redis 介绍 Redis 和 Memcached 都是非关系型数据库也称为 NoSQL 数据库,MySQL、 Mariadb、SQL Server、PostgreSQL、Oracle 数据库属于关系型数据 关系型数据库(RDBMS, Relational Database Management System)。 1.1 Redis 介绍 Redis(Remote Dictionary Se…...

冠达管理:核污染防治板块热度不减,建工修复等多只个股涨停
日本福岛核污染水排海引发商场担忧,核污染防治概念股表现持续活跃。 8月28日,建工修复(300958.SZ)、中电环保(300172.SZ)、捷强配备(300875.SZ)20CM强势涨停,中广核技&a…...

Unity关键概念
Unity是一款跨平台的游戏引擎和开发工具,用于创建2D和3D游戏、交互式内容和应用程序。它提供了一个强大的开发环境,使开发者能够轻松地设计、开发和部署高质量的游戏和应用程序。 以下是Unity的几个关键概念: 游戏对象(Game Obj…...

JDK配置环境变量(超详细)
先安装JDK再配置环境变量! JDK可以简单理解为就是java,JDK包含了java项目运行所需要的运行环境JRE,编译运行java程序的java虚拟机JVM。 jdk-8u201-windows-x64安装包(jdk1.8): 提取码:19xv …...

抢先体验|乐鑫推出 ESP32-S3-BOX-3 新一代开源 AIoT 开发套件
乐鑫科技 (688018.SH) 非常高兴地宣布其开发套件阵容的最新成员 ESP32-S3-BOX-3。这款完全开源的 AIoT 应用开发套件搭载乐鑫高性能 ESP32-S3 AI SoC,旨在突破传统开发板,成为新一代开发工具的引领者。 【乐鑫新品抢先体验】ESP32-S3-BOX-3 新一代开源 A…...

Java 语言实现归并排序算法
【引言】 归并排序算法是一种高效且稳定的排序算法。它采用分治法的思想,将数组反复分割成两个子数组,直到每个子数组只有一个元素。然后将这些子数组逐个合并,最终得到排序完毕的数组。本文将使用Java语言实现归并排序算法,并详细…...

【Python编程】将同一种图片分类到同一文件夹中
一、数据结构如下: 二、编程工具:Jupyter-Notebook 三、代码: import os import cv2 import shutilpath0os.getcwd()\\apple\\RGB path1os.getcwd()\\apple\\tof_confidence path2os.getcwd()\\apple\\tof_depth path3os.getcwd()\\apple\\…...

Web安全测试(四):XML注入和代码注入
一、前言 结合内部资料,与安全渗透部门同事合力整理的安全测试相关资料教程,全方位涵盖电商、支付、金融、网络、数据库等领域的安全测试,覆盖Web、APP、中间件、内外网、Linux、Windows多个平台。学完后一定能成为安全大佬! 全部…...

如何通过内网穿透实现外部网络对Spring Boot服务端接口的HTTP监听和调试?
文章目录 前言1. 本地环境搭建1.1 环境参数1.2 搭建springboot服务项目 2. 内网穿透2.1 安装配置cpolar内网穿透2.1.1 windows系统2.1.2 linux系统 2.2 创建隧道映射本地端口2.3 测试公网地址 3. 固定公网地址3.1 保留一个二级子域名3.2 配置二级子域名3.2 测试使用固定公网地址…...

深入理解c++特殊成员函数
深入理解c特殊成员函数 在c中,特殊成员函数有下面6个: 构造函数析构函数复制构造函数(拷贝构造函数)赋值运算符(拷贝运算符)移动构造函数(c11引入)移动运算符(c11引入) 以Widget类为例,其特殊成员函数的签名如下所示: class W…...

RecyclerView面试问答
RecycleView 和 ListView对比: 使用方法上 ListView:继承重写 BaseAdapter,自定义 ViewHolder 与 converView优化。 RecyclerView: 继承重写 RecyclerView.Adapter 与 RecyclerView.ViewHolder。设置 LayoutManager 来展示不同的布局样式 ViewHolder的编写规范化,ListVie…...

Redis 7 教程 数据持久化
总体 RDB 介绍 RDB 持久化以指定的时间间隔执行数据集的时间点快照 。 把某一时刻的数据和状态以文件的形式写到磁盘上,即使出现故障宕机,快照文件也不会丢失,数据的可靠性得到保证。快照文件就是RDB(Redis DataBase)文件(dump.rdb) 作用 在指定的时间间隔内将内存中的数…...

【ArcGIS微课1000例】0072:如何生成空间权重矩阵
严重声明:本文来自专栏《ArcGIS微课1000例:从点滴到精通》,为CSDN博客专家刘一哥GIS原创,原文及专栏地址为:(https://blog.csdn.net/lucky51222/category_11121281.html),谢绝转载或爬取!!! 文章目录 一、空间权重矩阵工具介绍二、ArcGIS生成空间权重矩阵三、注意事项…...

【芯片设计封装与测试】芯片测试目的、方法、分类及案例
目录 1.芯片测试概述(目的、方法) 1.1.测试在芯片产业价值链上的位置 2.测试如何体现在设计的过程中 2.1.半导体测试定义与基本工作机制 2.2.半导体测试环节分类及对应设备 2.3.设计验证 3.测试的各种类型 3.1.抽样测试和生产全测 3.2.测试相关…...

k8s集群证书过期解决
一、k8s集群证书过期解决 问题现象 K8S集群证书过期后,会导无法创建Pod,通过kubectl get nodes也无法获取信息,甚至dashboard也无法访问。 执行命令发现报错: Unable to connect to the server: x509: certificate has expire…...

Linux学习之Ubuntu 20.04在github下载源码安装Openresty 1.19.3.1
参考的博文:《在 Ubuntu 上使用源码安装 OpenResty》 《OpenResty 安装安装详解-Ubuntu》 《Linux学习之CentOS 7源码安装openresty》 https://openresty.org/en/download.html是官网下载网址,页面往下拉有下载的链接。 https://github.com/openresty…...

bootloader串口更新程序[瑕疵学习板]
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、储备知识二、程序步骤2.程序展示1.bootloader2.然后是主运行函数总结前言 很久没有更新文章了。最近工作太忙,没有学习很多的知识,然后这两天不忙了,就学习了一下bootloader的程序升级…...

浅谈视频汇聚平台EasyCVR视频平台在城市安全综合监测预警台风天气中的重要作用
夏日已至,台风和暴雨等极端天气频繁出现。在城市运行过程中,台风所带来的暴雨可能会导致城市内涝等次生灾害,引发交通瘫痪、地铁停运、管网泄漏爆管、路面塌陷、防洪排涝、燃气爆炸、供热安全、管廊安全、消防火灾等安全隐患,影响…...

GaussDB技术解读系列:高级压缩之OLTP表压缩
8月16日,第14届中国数据库技术大会(DTCC2023)在北京国际会议中心顺利举行。在GaussDB“五高两易”核心技术,给世界一个更优选择的专场,华为云数据库GaussDB首席架构师冯柯对华为云GaussDB数据库的高级压缩技术进行了详…...

管理类联考——英语二——实战篇——大作文——图表——静态图表——第一段
第一句:What is clearly presented in the above 图表类型 is the statistics of 主题词 1. 翻译:从上述图表类型中我们能够清晰地得知有关主题词1的数据。 [备注1]:本句对图表进行整体描述,无需描述具体各项内容所占比例,只需提出主题词的哪方面的有关数据…...