当前位置: 首页 > 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;其余每个元素均出现两次。找出那个只出现了一次的元素。 你必须设计并实现线性时间…...

C++设计模式:享元模式 (附文字处理系统中的字符对象案例)

什么是享元模式&#xff1f; 享元模式是一个非常实用的结构型设计模式&#xff0c;它的主要目的是节省内存&#xff0c;尤其在需要创建大量相似对象时。 通俗解释&#xff1a; 想象我们在写一本书&#xff0c;每个字母都需要表示出来。如果每个字母都单独用对象表示&#xff…...

android EditText密码自动填充适配

android上的密码&#xff08;其实不仅仅是密码&#xff0c;可以是用户名也可以是邮箱&#xff09;自动填充&#xff0c;是需要考虑适配的。 官方文档&#xff1a;https://developer.android.com/identity/autofill/autofill-optimize?hlzh-cn 什么是自动填充 手机厂商一般会…...

LeetCode 刷题笔记

LeetCode 刷题笔记 1. 20241218 &#xff08;1&#xff09;2447 std::gcd是C17引入的一个函数&#xff0c;用于计算两个整数的最大公因数。位于<numeric>头文件中。 #include <iostream> #include <numeric> // std::gcdint main() {int a 36;int b 60…...

【Java基础面试题034】Java泛型擦除是什么?

回答重点 泛型擦除指的是Java编译器在编译时将所有泛型信息删除的过程&#xff0c;以确保与Java1.4及之前的版本保持兼容 泛型参数在运行时会被替换为其上界&#xff08;通常是Object&#xff09;&#xff0c;这样一来在运行时无法获取泛型的实际类型。 作用&#xff1a;泛型…...

使用ssh命令远程登录服务器的两种便捷方式:简化ssh命令、创建bat文件

1. 简化ssh命令 使用记事本打开该路径C:\Users\<你的用户名>\.ssh\下的config文件&#xff0c;粘贴以下代码&#xff1a; Host myserverHostName 192.168.1.1(这里换成你的ip地址)User your_username(这里换成你的用户名)Port 22保存文件后现在在cmd中直接输入ssh myserv…...

access数据库代做/mysql代做/Sql server数据库代做辅导设计服务

针对Access数据库、MySQL以及SQL Server数据库的代做和辅导设计服务&#xff0c;以下是一些关键信息和建议&#xff1a; 一、服务概述 这些服务通常包括数据库的设计、创建、优化、维护以及相关的编程和查询编写等。无论是Access这样的桌面关系数据库管理系统&#xff08;RDB…...

第十七届山东省职业院校技能大赛 中职组“网络安全”赛项任务书正式赛题

第十七届山东省职业院校技能大赛 中职组“网络安全”赛项任务书-A 目录 一、竞赛阶段 二、竞赛任务书内容 &#xff08;一&#xff09;拓扑图 &#xff08;二&#xff09;模块A 基础设施设置与安全加固(200分) &#xff08;三&#xff09;B模块安全事件响应/网络安全数据取证/…...

Android学习(五)-Kotlin编程语言-面向对象中的 继承-构造函数-接口三模块学习

首先&#xff0c;我们需要定义一个 Person 类&#xff1a; open class Person {var name ""var age 0fun eat() {println("$name is eating.")} } 注意&#xff0c;Person 类前面加上了 open 关键字&#xff0c;表示这个类可以被继承。在 Kotlin 中&am…...

滑动窗口 + 算法复习

维护一个满足条件的窗口大小&#xff0c;然后进行双指针移动 1.最长子串 题目链接&#xff1a;1.最长子串 - 蓝桥云课 #include<bits/stdc.h> #define int long long using namespace std; string s; int k; signed main() {int max_len0,left0;cin>>s>>k;…...

贪心算法 greedy

文章目录 参考贪心算法[Leetcode455 分发饼干](https://leetcode.cn/problems/assign-cookies/description/)分析题解 [Leetcode135 分发糖果](https://leetcode.cn/problems/assign-cookies/description/)分析题解 leetcode435无重叠区间分析题解 参考 https://github.com/ch…...