当前位置: 首页 > article >正文

代理模式简述

目录

一、主要角色

二、类型划分

三、静态代理

示例

缺点

四、动态代理

JDK动态代理

示例

 缺点

CGLib动态代理

导入依赖

示例

五、Spring AOP


        代理模式是一种结构型设计模式,通过代理对象控制对目标对象的访问,可在不改变目标对象情况下增强其功能,隐藏实现细节。

一、主要角色

  • Subject(业务接口类):可以是抽象类或接口
  • RealSubject(业务实现类):具体的业务执行,即被代理的对象
  • Proxy(代理类):RealSubject的代理

二、类型划分

根据代理的创建时期,可分为静态代理和动态代理

  • 静态代理:由程序员创建或工具自动生成代理类源代码并编译,程序运行前代理类的字节码文件已经存在;
  • 动态代理:在程序运行时运用反射机制动态创建而成

为方便下面的讲解,我们先提前创建业务接口类和业务实现类

//业务接口类
public interface HouseSubject {void rentHouse();
}
//业务实现类(被代理类)
public class RealHouseSubject implements HouseSubject {@Overridepublic void rentHouse() {System.out.println("我是房东,我出租房子");}
}

三、静态代理

示例
//代理类
public class HouseProxy implements HouseSubject{//中介出售房子前要先有房东的授权private HouseSubject houseSubject;public HouseProxy(HouseSubject houseSubject) {this.houseSubject = houseSubject;}@Overridepublic void rentHouse() {System.out.println("我是中介,我开始代理房东出租房子");houseSubject.rentHouse();System.out.println("我是中介,代理结束");}
}

使用代理类执行

public class Main {public static void main(String[] args) {//创建代理对象HouseSubject subject=new HouseProxy(new RealHouseSubject());subject.rentHouse();}
}

缺点
  • 为每个被代理类编写代理类,代码冗余,随着业务的发展,类数量膨胀,项目管理难度增大
  • 被代理类接口变化时,所有相关代理类都需修改,易出错,可维护性差
  • 只能服务特定被代理类,难以应对新类和多变的额外逻辑需求,缺乏灵活性

四、动态代理

JDK动态代理
示例

自定义JDKInvocationHandler 并重写invoke(),在invoke()中会调用目标方法,并自定义一些处理逻辑

import lombok.extern.slf4j.Slf4j;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;//实现 InvocationHandler接口可以被代理对象的方法进行功能增强
@Slf4j
public class JDKInvocationHandler implements InvocationHandler {//目标类private Object target;public JDKInvocationHandler(Object target) {this.target = target;}/*** 调用目标方法,并对方法进行增强* @param proxy 代理对象* @param method 代理对象需要实现的方法* @param args method方法所对应的参数*/@Overridepublic Object invoke(Object proxy, Method method, Object[] args) throws Throwable {log.info("JDK动态代理开始");//调用目标函数Object result=method.invoke(target,args);log.info("JDK动态代理结束");return null;}
}

创建代理对象,执行逻辑 

import java.lang.reflect.Proxy;public class Main {public static void main(String[] args) {RealHouseSubject target=new RealHouseSubject();//通过被代理类、被代理类实现的接口、方法调用处理器来创建一个代理类/***  ClassLoader loader 类加载器,用于加载代理对象*  Class<?>[] interfaces 被代理类实现的一些接口(jdk只能代理实现了接口的类)*  java.lang.reflect.InvocationHandler h 实现了InvocationHandler接口的对象*/HouseSubject proxy=(HouseSubject) Proxy.newProxyInstance(target.getClass().getClassLoader(),new Class[]{HouseSubject.class},new JDKInvocationHandler(target));//使用代理类proxy.rentHouse();}
}

 缺点

只能代理实现了接口的类,不能代理普通类

CGLib动态代理

导入依赖
<dependency><groupId>cglib</groupId><artifactId>cglib</artifactId><version>3.3.0</version>
</dependency>
示例
import lombok.extern.slf4j.Slf4j;
import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;
import java.lang.reflect.Method;@Slf4j
public class CGLibMethodInterceptor implements MethodInterceptor {private Object target;public CGLibMethodInterceptor(Object target) {this.target = target;}/**** @param o 被代理的对象* @param method 目标方法* @param objects 方法入参* @param methodProxy 用于调用原始方法* @return* @throws Throwable*/@Overridepublic Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {//代理增强内容System.out.println("CGLib代理开始");//通过反射调用被代理的方法Object retVal=methodProxy.invoke(target,objects);System.out.println("CGLib代理结束");return retVal;}
}
import net.sf.cglib.proxy.Enhancer;public class Main {public static void main(String[] args) {HouseSubject target=new RealHouseSubject();HouseSubject proxy= (HouseSubject)Enhancer.create(target.getClass(),new CGLibMethodInterceptor(target));proxy.rentHouse();}
}

五、Spring AOP

Spring AOP是基于动态代理实现的,动态代理有JDK和CGLIB两种方式,运行时使用哪种方式与项目配置和代理的对象有关。

proxy-target-class="false"情况下,若代理对象实现接口,默认使用JDK动态代理;若未实现接口,则会用CGLIB动态代理。当然,即便对象实现接口,也能通过xml配置proxy-target-class="true"或在配置类上使用注解@EnableAspectJAutoProxy(proxyTargetClass = true) 强制使用CGLIB动态代理。

Spring Boot 2.X开始默认使用CGLIB代理,也就是proxy-target-class="true"。

二者各有优劣,需依项目实际情况抉择。JDK动态代理优势在于基于Java原生支持,无需额外依赖,性能较好,适用于对性能要求高且目标对象有接口的场景;但是只能代理实现了接口的对象。

CGLIB动态代理优势在于能代理无接口的普通类,功能更强大、灵活性更高;但是需额外注入依赖,且通过继承创建代理,若类被final修饰则无法代理,生成代理对象的性能开销相对较大。

相关文章:

代理模式简述

目录 一、主要角色 二、类型划分 三、静态代理 示例 缺点 四、动态代理 JDK动态代理 示例 缺点 CGLib动态代理 导入依赖 示例 五、Spring AOP 代理模式是一种结构型设计模式&#xff0c;通过代理对象控制对目标对象的访问&#xff0c;可在不改变目标对象情况下增强…...

Operator 开发入门系列(一):Hello World

背景 我们公司最近计划将产品迁移到 Kubernetes 环境。 为了更好地管理和自动化我们的应用程序&#xff0c;我们决定使用 Kubernetes Operator。 本系列博客将记录我们学习和开发 Operator 的过程&#xff0c;希望能帮助更多的人入门 Operator 开发。 目标读者 对 Kubernete…...

【Docker】运行错误提示 unknown shorthand flag: ‘d‘ in -d ----详细解决方法

使用docker拉取Dify的时候遇到错误 错误提示 unknown shorthand flag: d in -dUsage: docker [OPTIONS] COMMAND [ARG...]错误原因解析 出现 unknown shorthand flag: d in -d 的根本原因是 Docker 命令格式与当前版本不兼容&#xff0c;具体分为以下两种情况&#xff1a; 新…...

【AI插件开发】Notepad++ AI插件开发实践:实现对话窗口功能

引言 之前的文章已经介绍实现了AI对话窗口&#xff0c;但只有个空壳&#xff0c;没有实现功能。本次将集中完成对话窗口的功能&#xff0c;主要内容为&#xff1a; 模型动态切换&#xff1a;支持运行时加载配置的AI模型列表交互式输入处理&#xff1a;实现多行文本输入与Ctrl…...

在激烈竞争下B端HMI设计怎样打造独特用户体验?

在当今数字化高度发展的时代&#xff0c;B 端市场竞争愈发激烈。对于 B 端 HMI&#xff08;人机界面&#xff09;设计而言&#xff0c;打造独特的用户体验已成为在竞争中脱颖而出的关键因素。B 端用户在复杂的工作场景中&#xff0c;对 HMI 设计有着独特的需求和期望&#xff0…...

【Netty篇】Handler Pipeline 详解

目录 一、 Handler & Pipeline——流水线上的“特种部队”与“生产线”1、 ChannelHandler —— 流水线上的“特种兵”&#x1f46e;‍♂️2、 ChannelPipeline —— 生产线上的“接力赛跑”&#x1f3c3;‍♀️&#x1f3c3;‍♂️ 二、 代码实例1、 服务端代码示例2、 客…...

计算机网络 - UDP协议

通过一些问题来讨论 UDP 协议 什么是 UDP&#xff1f;举几个应用了 UDP 协议的例子UDP 与 TCP 有啥区别&#xff1f;&#xff08;PS&#xff1a;介绍三四个就可以了&#xff0c;不用说太多&#xff09;具体 UDP 是不可靠的&#xff0c;那你觉得如何实现一个可靠的 UDP &#x…...

16-算法打卡-哈希表-两个数组的交集-leetcode(349)-第十六天

1 题目地址 349. 两个数组的交集 - 力扣&#xff08;LeetCode&#xff09;349. 两个数组的交集 - 给定两个数组 nums1 和 nums2 &#xff0c;返回 它们的 交集 。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序 。 示例 1&#xff1a;输入&#xff1a;nu…...

java + spring boot + mybatis 通过时间段进行查询

前端传来的只有日期内容&#xff0c;如&#xff1a;2025-04-17 需要在日期内容的基础上补充时间部分&#xff0c;代码示例&#xff1a; /*** 日志查询&#xff08;分页查询&#xff09;* param recordLogQueryDTO 查询参数对象* return 日志列表*/Overridepublic PageBean<…...

AI与物联网的深度融合:开启智能生活新时代

在当今数字化时代&#xff0c;人工智能&#xff08;AI&#xff09;和物联网&#xff08;IoT&#xff09;作为两大前沿技术&#xff0c;正在加速融合&#xff0c;为我们的生活和工作带来前所未有的变革。这种融合不仅提升了设备的智能化水平&#xff0c;还为各行各业带来了新的机…...

浔川AI翻译v7.0更新预告

亲爱的浔川AI翻译用户&#xff1a; 感谢您一直以来的支持&#xff01;浔川AI翻译自推出以来&#xff0c;已迭代6个版本&#xff0c;其中**v2.0和v4.0因技术问题&#xff08;翻译结果显示异常、注册失败、密码找回功能失效等&#xff09;**被迫下架。我们深知这些问题影响了您…...

helm账号密码加密

1、安装工具 sudo apt update sudo apt install gnupg -y wget https://github.com/getsops/sops/releases/download/v3.10.2/sops-v3.10.2.linux.amd64 mv sops-v3.10.2.linux.amd64 /usr/local/bin/sops chmod x /usr/local/bin/sops2、生成加密文件 gpg --full-generate-…...

Flink 编程基础:Scala 版 DataStream API 入门

大家好&#xff01;我是心海 流处理技术在大数据时代正变得越来越重要&#xff0c;而 Apache Flink 作为领先的流处理引擎&#xff0c;凭借其高性能、低延迟和丰富的 API 受到了广泛关注。本文将以 Scala 语言为例&#xff0c;详细讲解 Flink DataStream API 的基本编程模型&am…...

实战|使用环信Flutter SDK构建鸿蒙HarmonyOS应用及推送配置

本文为大家介绍如何在 Flutter 环境创建 Harmony 项目并集成环信即时通讯IM以及环信 Flutter Harmony 推送配置。 已经基于环信的 Flutter 项目也可以参考本文适配鸿蒙端。 一、开发环境要求 前置条件 1.安装DevEco-Studio 2.安装模拟器 DevEco-Studio 下载与操作指导&…...

HTML5好看的水果蔬菜在线商城网站源码系列模板5

文章目录 1.设计来源1.1 主界面1.2 关于我们1.3 商品服务1.4 果蔬展示1.5 联系我们1.6 商品具体信息1.7 登录注册 2.效果和源码2.1 动态效果2.2 源代码 源码下载万套模板&#xff0c;程序开发&#xff0c;在线开发&#xff0c;在线沟通 作者&#xff1a;xcLeigh 文章地址&#…...

宜搭与金蝶互通——连接器建立

一、 进入连接器工厂 图1 连接器入口 二、 新建连接器 图2 新建连接器第一步 1、 连接器显示名,如图2中①所示; 2、 图2中②域名,是金蝶系统API接口里面的“完整服务地址”com之前的信息,不含“https”,如图3中①所示; 3、 Base Url通常为“/”,如图2…...

SP7733:HPYNOS - Happy Numbers I(参考我之前的文章,哈希)

题目大意 我们定义“破坏”整数的过程是对其每一位上的数字的平方求和成为一个新数&#xff0c;如果一个数在经过若干次“破坏”以后变成了 1&#xff0c;那么这个数就是一个高兴的数字&#xff0c;输出变化次数&#xff0c;否则如果永远不会变成 1&#xff0c;输出 −1。 例如…...

《Java 泛型的作用与常见用法详解》

大家好呀&#xff01;&#x1f44b; 今天我们要聊的是Java中一个超级重要但又让很多初学者头疼的概念——泛型(Generics)。带你彻底搞懂它&#xff01;&#x1f4aa; 准备好你的小本本&#xff0c;我们开始啦&#xff5e;&#x1f4dd; 一、为什么需要泛型&#xff1f;&#x…...

【JavaWeb】详细讲解 HTTP 协议

文章目录 一、HTTP简介1.1 概念1.2 特点 二、协议2.1 HTTP-请求协议&#xff08;1&#xff09;GET方式&#xff08;2&#xff09;POST方式&#xff08;3&#xff09;GET和POST的区别&#xff1a; 2.2 HTTP-响应协议&#xff08;1&#xff09;格式&#xff08;2&#xff09;响应…...

【android bluetooth 框架分析 02】【Module详解 4】【Btaa 模块介绍】

1. 背景 我们在上一篇文章中介绍 HciHal 模块时&#xff0c;有如下代码 // system/gd/hal/hci_hal_android_hidl.ccvoid ListDependencies(ModuleList* list) const {list->add<SnoopLogger>();if (common::init_flags::btaa_hci_is_enabled()) {list->add<ac…...

“星睿O6” AI PC开发套件评测 - Windows on Arm 安装指南和性能测评

引言 Radxa联合此芯科技和安谋科技推出全新的"星睿O6"迷你 ITX 主板。该系统搭载了 CIX P1&#xff08;CD8180&#xff09;12 核 Armv9 处理器&#xff0c;拥有高达30T算力的NPU和高性能的GPU&#xff0c;最高配备64GB LPDDR内存&#xff0c;并提供了如 5GbE、HDMI …...

Python 调用 YOLOv11 ONNX

Python 调用 YOLO ONNX 1 下载ONNX文件2 Python代码 1 下载ONNX文件 ONNX下载地址 2 Python代码 import cv2 from ultralytics import YOLOdef check(yolo:str, path:str):# 加载 YOLOv11model YOLO(yolo)# 读取图片img cv2.imread(path)# 推理&#xff08;可以传文件路径…...

数据通信学习笔记之OSPF路由汇总

区域间路由汇总 路由汇总又被称为路由聚合&#xff0c;即是将一组前缀相同的路由汇聚成一条路由&#xff0c;从而达到减小路由表规模以及优化设备资源利用率的目的&#xff0c;我们把汇聚之前的这组路由称为精细路由或明细路由&#xff0c;把汇聚之后的这条路由称为汇总路由或…...

ASP.NET Core Web API 配置系统集成

文章目录 前言一、配置源与默认设置二、使用步骤1&#xff09;创建项目并添加配置2&#xff09;配置文件3&#xff09;强类型配置类4&#xff09;配置Program.cs5&#xff09;控制器中使用配置6&#xff09;配置优先级测试7&#xff09;动态重载配置测试8&#xff09;运行结果示…...

如何判断单片机性能极限?

目录 1、CPU 负载 2、内存使用情况 3、实时性能 4、外设带宽 5、功耗与温度 在嵌入式系统设计中&#xff0c;当系统变得复杂、功能增加时&#xff0c;单片机可能会逐渐逼近其性能极限。及时识别这些极限点对于保证产品质量、稳定性和用户体验至关重要。 当你的嵌入式系统…...

AI在多Agent协同领域的核心概念、技术方法、应用场景及挑战 的详细解析

以下是 AI在多Agent协同领域的核心概念、技术方法、应用场景及挑战 的详细解析&#xff1a; 1. 多Agent协同的定义与核心目标 多Agent系统&#xff08;MAS, Multi-Agent System&#xff09;&#xff1a; 由多个独立或协作的智能体&#xff08;Agent&#xff09;组成&#xff…...

1.凸包、极点、极边基础概念

目录 1.凸包 2.调色问题 3.极性(Extrem) 4.凸组合(Convex Combination) 5.问题转化(Strategy)​编辑 6.In-Triangle test 7.To-Left-test 8.极边&#xff08;Extream Edges&#xff09; 1.凸包 凸包就是上面蓝色皮筋围出来的范围 这些钉子可以转换到坐标轴中&#xff0…...

OSCP - Proving Grounds - DriftingBlues6

主要知识点 路径爆破dirtycow内核漏洞提权 具体步骤 总体来讲&#xff0c;这台靶机还是比较直接的&#xff0c;没有那么多的陷阱,非常适合用来学习 依旧是nmap开始,只开放了80端口 Nmap scan report for 192.168.192.219 Host is up (0.42s latency). Not shown: 65534 cl…...

深度理解指针之例题

文章目录 前言题目分析与讲解涉及知识点 前言 对指针有一定了解后&#xff0c;讲一下一道初学者的易错题 题目分析与讲解 先定义一个数组跟一个指针变量 然后把数组名赋值给指针变量————也就是把首地址传到pulPtr中 重点是分析这一句&#xff1a; *&#xff08;pulPtr…...

java 设计模式之策略模式

简介 策略模式&#xff1a;策略模式可以定制目标对象的行为&#xff0c;它尅通过传入不同的策略实现&#xff0c;来配置目标对象的行为。使用策略模式&#xff0c;就是为了定制目标对象在某个关键点的行为。 策略模式中的角色&#xff1a; 上下文类&#xff1a;持有一个策略…...