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

代理模式(JDK,CGLIB动态代理,AOP切面编程)

代理模式是一种结构型设计模式,它通过一个代理对象作为中间层来控制对目标对象的访问,从而增强或扩展目标对象的功能,同时保持客户端对目标对象的使用方式一致。

代理模式在Java中的应用,例如

1.统一异常处理

2.Mybatis使用代理

3.Spring AOP实现原理

4.日志框架

讲些空话,大话,大白话:

接口:定义行为规范,为了多态

实现类:对具体接口的实现(目标对象),被代理的类

代理类:做功能增强与扩展

静态代理:(常用于代理接口的实现类,也可以代理普通类)

代理接口的实现类

定义接口

public interface Service {
    void doWork();
}

 实现目标对象

public class RealService implements Service {
    @Override
    public void doWork() {
        System.out.println("RealService 正在执行工作。");
    }
}

创建代理类

public class ServiceProxy implements Service {
    private final Service realService; // 持有目标对象的引用

    //我还可以引入些其他,用来在doWork方法前后做增强或者扩展

    //private Xxxx   xxxx;可以构造中做初始化

    public ServiceProxy(Service realService) {
        this.realService = realService;
    }

    @Override
    public void doWork() {
        System.out.println("代理:调用方法之前记录日志...");
        realService.doWork(); // 调用目标对象的方法
        System.out.println("代理:调用方法之后记录日志...");
    }
}

测试静态代理

public class StaticProxyExample {
    public static void main(String[] args) {
        // 创建目标对象
        Service realService = new RealService();

        // 创建代理对象,并传入目标对象
        Service proxy = new ServiceProxy(realService);

        // 调用代理对象的方法
        proxy.doWork();
    }
}

静态代理在Boot中实际使用

---------------------------------------------------------------------------------------------------------------

代理普通类

// 目标类
public class RealService {
    public void doWork() {
        System.out.println("RealService 正在工作...");
    }
}

// 代理类
public class ServiceProxy {
    private RealService realService;

    public ServiceProxy(RealService realService) {
        this.realService = realService;
    }

    public void doWork() {
        System.out.println("代理: 调用方法之前...");
        realService.doWork();
        System.out.println("代理: 调用方法之后...");
    }
}

// 使用代理
public class Main {
    public static void main(String[] args) {
        RealService realService = new RealService();
        ServiceProxy proxy = new ServiceProxy(realService);
        proxy.doWork();
    }
}

JDK动态代理 

1.JDK 动态代理的特点
  1. 必须基于接口

    • 代理对象必须实现目标类的接口。
    • 如果目标类没有接口,JDK 动态代理无法使用。
  2. 运行时动态生成代理对象

    • 代理类的代码不是在编译时生成,而是在运行时动态创建。
  3. 通过 InvocationHandler 实现增强逻辑

    • 使用 InvocationHandler 接口处理方法的调用逻辑。
    • 可以对方法调用进行拦截,并添加额外的增强功能。
  4. 生成的代理类是目标接口的实现类

    • 代理对象的类型是接口类型,不能直接当作目标类使用。

2. JDK 动态代理的核心类
(1) Proxy
  • Java 动态代理的核心类,用于生成代理对象。
  • 方法:
    Proxy.newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h)
    
    • ClassLoader loader:目标类的类加载器,用于加载代理对象。
    • Class<?>[] interfaces:目标类实现的接口数组。
    • InvocationHandler h:调用处理器,用于定义代理对象的方法逻辑。
(2) InvocationHandler 接口
  • 用于定义代理对象的行为。
  • 核心方法:
    Object invoke(Object proxy, Method method, Object[] args) throws Throwable
    
    • proxy:代理对象本身。
    • method:当前调用的方法。
    • args:调用方法的参数。

3. JDK 动态代理的实现步骤
(1) 定义接口和实现类

// 定义接口
public interface Service {
    void doWork();
}

// 实现类(目标类)
public class RealService implements Service {
    @Override
    public void doWork() {
        System.out.println("RealService 正在执行工作...");
    }
}

(2) 创建 InvocationHandler 该接口作用是方法拦截

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class ServiceInvocationHandler implements InvocationHandler {
    private Object target; // 持有目标对象的引用

    public ServiceInvocationHandler(Object target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("代理: 调用方法之前记录日志...");
        Object result = method.invoke(target, args); // 调用目标方法
        System.out.println("代理: 调用方法之后记录日志...");
        return result;
    }
}

(3) 创建代理对象

import java.lang.reflect.Proxy;

public class Main {
    public static void main(String[] args) {
        // 创建目标对象
        Service realService = new RealService();

        // 创建 InvocationHandler
        ServiceInvocationHandler handler = new ServiceInvocationHandler(realService);

        // 生成代理对象
        Service proxy = (Service) Proxy.newProxyInstance(
                realService.getClass().getClassLoader(), // 类加载器
                new Class<?>[]{Service.class},          // 实现的接口
                handler                                 // 调用处理器
        );

        // 调用代理对象的方法
        proxy.doWork();
    }
}

CGLIB代理

相关文章:

代理模式(JDK,CGLIB动态代理,AOP切面编程)

代理模式是一种结构型设计模式&#xff0c;它通过一个代理对象作为中间层来控制对目标对象的访问&#xff0c;从而增强或扩展目标对象的功能&#xff0c;同时保持客户端对目标对象的使用方式一致。 代理模式在Java中的应用,例如 1.统一异常处理 2.Mybatis使用代理 3.Spring…...

【Leetcode 热题 100】236. 二叉树的最近公共祖先

问题背景 给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。 最近公共祖先的定义为&#xff1a;对于有根树 T T T 的两个节点 p p p、 q q q&#xff0c;最近公共祖先表示为一个节点 x x x&#xff0c;满足 x x x 是 p p p、 q q q 的祖先且 x x x 的深度尽可能大…...

Go框架比较:goframe、beego、iris和gin

由于工作需要&#xff0c;这些年来也接触了不少的开发框架&#xff0c;Golang的开发框架比较多&#xff0c;不过基本都是Web"框架"为主。这里稍微打了个引号&#xff0c;因为大部分"框架"从设计和功能定位上来讲&#xff0c;充其量都只能算是一个组件&…...

Kafka Streams 在监控场景的应用与实践

作者&#xff1a;来自 vivo 互联网服务器团队- Pang Haiyun 介绍 Kafka Streams 的原理架构&#xff0c;常见配置以及在监控场景的应用。 一、背景 在当今大数据时代&#xff0c;实时数据处理变得越来越重要&#xff0c;而监控数据的实时性和可靠性是监控能力建设最重要的一环…...

数据结构 -- 二叉树

目录 1、二叉树概念及结构 1.1、概念 1.2、特殊的二叉树 1.3、二叉树的性质 1.4、二叉树的存储结构 1.4.1、顺序存储 -- 看截图&#xff1a;二叉树的顺序存储 1.4.2、链式存储 -- 非完全二叉树用这种方式存储 2、二叉树的遍历 2.1、前序、中序以及后序遍历2.2、层序遍…...

redis数据转移

可能有时候因为硬件的原因我们我们需要更换服务器&#xff0c;如果更换服务器的话&#xff0c;那我们redis的数据该怎样转移呢&#xff0c;按照一下步骤即可完成redis数据的转移 1.进入redis客户端 2.使用 bgsave命令进行数据的备份&#xff0c;此命令完成后会在你的redis安装目…...

Ubuntu Netlink 套接字使用介绍

Netlink 套接字 是 Linux 特有的一种 IPC&#xff08;进程间通信&#xff09;机制&#xff0c;用于用户态进程和内核模块之间的通信。它可以用来完成路由管理、设备通知、网络状态更新等任务。 1. Netlink 的基本工作原理 Netlink 是一种双向通信机制。Netlink 消息分为请求和…...

spring boot密码加密方式

1. BCrypt 原理 BCrypt是一种专为密码哈希设计的算法&#xff0c;它被广泛认为是安全的选择之一。它不仅是一个单向函数&#xff08;即只能加密不能解密&#xff09;&#xff0c;而且还内置了盐&#xff08;salt&#xff09;生成机制来防止彩虹表攻击。BCrypt的一个重要特点是…...

springboot根据租户id动态指定数据源

代码地址 码云地址springboot根据租户id动态指定数据源: springboot根据租户id指定动态数据源,结合mybatismysql多数源下的事务管理 创建3个数据库和对应的表 sql脚本在下图位置 代码的执行顺序 先设置主数据库的数据源配置目标数据源和默认数据源有了主库的数据源&#xff…...

使用C语言编写UDP循环接收并打印消息的程序

使用C语言编写UDP循环接收并打印消息的程序 前提条件程序概述伪代码C语言实现编译和运行C改进之自由设定端口注意事项在本文中,我们将展示如何使用C语言编写一个简单的UDP服务器程序,该程序将循环接收来自指定端口的UDP消息,并将接收到的消息打印到控制台。我们将使用POSIX套…...

【AI】✈️问答页面搭建-内网穿透公网可访问!

目录 &#x1f44b;前言 &#x1f440;一、后端改动 &#x1f331;二、内网穿透 &#x1f49e;️三、前端改动 &#x1f379;四、测试 &#x1f4eb;五、章末 &#x1f44b;前言 小伙伴们大家好&#xff0c;上次本地搭建了一个简单的 ai 页面&#xff0c;实现流式输出问答…...

计算机毕业设计原创定制(免费送源码):NodeJS+MVVM+MySQL 樱花在线视频网站

目 录 摘要 1 1 绪论 1 1.1研究背景 1 1.2系统设计思想 1 1.3B/S体系工作原理 1 1.4node.js主要功能 2 1.5论文结构与章节安排 3 2 樱花在线视频网站分析 4 2.1 可行性分析 4 2.2 系统流程分析 4 2.2.1数据增加流程 5 2.3.2数据修改流程 5 2.3.3数据删除流程 5 …...

ECharts热力图-笛卡尔坐标系上的热力图,附视频讲解与代码下载

引言&#xff1a; 热力图&#xff08;Heatmap&#xff09;是一种数据可视化技术&#xff0c;它通过颜色的深浅变化来表示数据在不同区域的分布密集程度。在二维平面上&#xff0c;热力图将数据值映射为颜色&#xff0c;通常颜色越深表示数据值越大&#xff0c;颜色越浅表示数…...

【Lua热更新】下篇

上篇链接&#xff1a;【Lua热更新】上篇 文章目录 三、xLua热更新&#x1f4d6;1.概述&#x1f4da;︎2.导入xLua框架&#x1f516;3. C#调用Lua3.1Lua解析器3.2Lua文件夹的重定向3.3Lua解析器管理器3.4全局变量获取3.5全局函数获取3.6映射到List和Dictionary3.7映射到类3.8映…...

Facebook 与数字社交的未来走向

随着数字技术的飞速发展&#xff0c;社交平台的角色和形式也在不断演变。作为全球最大社交平台之一&#xff0c;Facebook&#xff08;现Meta&#xff09;在推动数字社交的进程中扮演了至关重要的角色。然而&#xff0c;随着互联网的去中心化趋势和新技术的崛起&#xff0c;Face…...

微信小程序实现二维码海报保存分享功能

首先在写这个二维码分享海报的时候试过很多方法&#xff0c;比如&#xff1a;canvas中的这个createCanvasContext创建上下文的方法&#xff0c;去网上一搜就是一大堆&#xff0c;但其实这个方法已经被废弃了。Canvas 实例&#xff0c;可通过 SelectorQuery 获取。这是绘制背景图…...

Android 搭建AIDL Client和Server端,双向通信

一、背景 使用AIDL,搭建Client和Server端,实现跨进程通讯,即两个应用之间可以相互通讯。这里列举AIDL实现的方式和需注意的细节&#xff0c;并附上源码。 二、实现方式 2.1 定义AIDL需要的接口,名字为xxx.aidl,Client和Server端 AIDL接口的包名和aidl文件必须一致&#xff0c…...

深度学习从入门到精通——图像分割实战DeeplabV3

DeeplabV3算法 参数配置关于数据集的配置训练集参数 数据预处理模块DataSet构建模块测试一下数据集去正则化模型加载模块DeepLABV3 参数配置 关于数据集的配置 parser argparse.ArgumentParser()# Datset Optionsparser.add_argument("--data_root", typestr, defa…...

STM32-笔记5-按键点灯(中断方法)

1、复制03-流水灯项目&#xff0c;重命名06-按键点灯&#xff08;中断法&#xff09; 在\Drivers\BSP目录下创建一个文件夹exti&#xff0c;在该文件夹下&#xff0c;创建两个文件exti.c和exti.h文件&#xff0c;并且把这两个文件加载到项目中&#xff0c;打开项目工程文件 加载…...

C++ 只出现一次的数字 - 力扣(LeetCode)

点击链接即可查看题目&#xff1a;136. 只出现一次的数字 - 力扣&#xff08;LeetCode&#xff09; 一、题目 给你一个 非空 整数数组 nums &#xff0c;除了某个元素只出现一次以外&#xff0c;其余每个元素均出现两次。找出那个只出现了一次的元素。 你必须设计并实现线性时间…...

深入剖析AI大模型:大模型时代的 Prompt 工程全解析

今天聊的内容&#xff0c;我认为是AI开发里面非常重要的内容。它在AI开发里无处不在&#xff0c;当你对 AI 助手说 "用李白的风格写一首关于人工智能的诗"&#xff0c;或者让翻译模型 "将这段合同翻译成商务日语" 时&#xff0c;输入的这句话就是 Prompt。…...

解锁数据库简洁之道:FastAPI与SQLModel实战指南

在构建现代Web应用程序时&#xff0c;与数据库的交互无疑是核心环节。虽然传统的数据库操作方式&#xff08;如直接编写SQL语句与psycopg2交互&#xff09;赋予了我们精细的控制权&#xff0c;但在面对日益复杂的业务逻辑和快速迭代的需求时&#xff0c;这种方式的开发效率和可…...

CentOS下的分布式内存计算Spark环境部署

一、Spark 核心架构与应用场景 1.1 分布式计算引擎的核心优势 Spark 是基于内存的分布式计算框架&#xff0c;相比 MapReduce 具有以下核心优势&#xff1a; 内存计算&#xff1a;数据可常驻内存&#xff0c;迭代计算性能提升 10-100 倍&#xff08;文档段落&#xff1a;3-79…...

【机器视觉】单目测距——运动结构恢复

ps&#xff1a;图是随便找的&#xff0c;为了凑个封面 前言 在前面对光流法进行进一步改进&#xff0c;希望将2D光流推广至3D场景流时&#xff0c;发现2D转3D过程中存在尺度歧义问题&#xff0c;需要补全摄像头拍摄图像中缺失的深度信息&#xff0c;否则解空间不收敛&#xf…...

对WWDC 2025 Keynote 内容的预测

借助我们以往对苹果公司发展路径的深入研究经验&#xff0c;以及大语言模型的分析能力&#xff0c;我们系统梳理了多年来苹果 WWDC 主题演讲的规律。在 WWDC 2025 即将揭幕之际&#xff0c;我们让 ChatGPT 对今年的 Keynote 内容进行了一个初步预测&#xff0c;聊作存档。等到明…...

2025 后端自学UNIAPP【项目实战:旅游项目】6、我的收藏页面

代码框架视图 1、先添加一个获取收藏景点的列表请求 【在文件my_api.js文件中添加】 // 引入公共的请求封装 import http from ./my_http.js// 登录接口&#xff08;适配服务端返回 Token&#xff09; export const login async (code, avatar) > {const res await http…...

在鸿蒙HarmonyOS 5中使用DevEco Studio实现录音机应用

1. 项目配置与权限设置 1.1 配置module.json5 {"module": {"requestPermissions": [{"name": "ohos.permission.MICROPHONE","reason": "录音需要麦克风权限"},{"name": "ohos.permission.WRITE…...

C++ Visual Studio 2017厂商给的源码没有.sln文件 易兆微芯片下载工具加开机动画下载。

1.先用Visual Studio 2017打开Yichip YC31xx loader.vcxproj&#xff0c;再用Visual Studio 2022打开。再保侟就有.sln文件了。 易兆微芯片下载工具加开机动画下载 ExtraDownloadFile1Info.\logo.bin|0|0|10D2000|0 MFC应用兼容CMD 在BOOL CYichipYC31xxloaderDlg::OnIni…...

Mysql8 忘记密码重置,以及问题解决

1.使用免密登录 找到配置MySQL文件&#xff0c;我的文件路径是/etc/mysql/my.cnf&#xff0c;有的人的是/etc/mysql/mysql.cnf 在里最后加入 skip-grant-tables重启MySQL服务 service mysql restartShutting down MySQL… SUCCESS! Starting MySQL… SUCCESS! 重启成功 2.登…...

关于uniapp展示PDF的解决方案

在 UniApp 的 H5 环境中使用 pdf-vue3 组件可以实现完整的 PDF 预览功能。以下是详细实现步骤和注意事项&#xff1a; 一、安装依赖 安装 pdf-vue3 和 PDF.js 核心库&#xff1a; npm install pdf-vue3 pdfjs-dist二、基本使用示例 <template><view class"con…...