SpringAOP原理:手写动态代理实现

news2024/11/24 18:28:53

0、基础知识

        AOP我们知道,是在不修改源代码的情况下,为代码添加一些新功能的技术。通过动态代理,可以在不修改原始类代码的前提下,对方法进行拦截和增强。
        动态代理常用于在不改变原有业务逻辑的情况下,对方法的调用进行额外的处理,比如日志记录、性能监控、事务管理等。它实现了面向切面编程(AOP)的核心概念。

1、动态代理  

        AOP其实就是先通过“一些办法”拿到“代理对象”,再对这个代理对象添加新方法。

动态代理的两种办法:

1.1 JDK代理:基于接口的动态代理技术。

        方法:通过目标接口,创建接口实现类,动态地在运行时内存里生成代理对象,其拥有目标对象的原方法实现,最后通过代理对象来增加新功能。

        看文字有些抽象,现在手动用代码实现一个JDK代理的AOP技术,根据jdk1.8手册找到Proxy类,通过newInstance方法实现动态代理对象的创建。

 “Proxy提供了创建动态代理类和实例的静态方法,它也是由这些方法创建的所有动态代理类的超类。”

(1)准备接口和实现类

//=========================接口============================
public interface UserDao {
    public int add(int a,int b);
    public String update(String id);
}

//=========================实现类============================
public class UserDaoImpl implements UserDao{
    @Override
    public int add(int a, int b) {
        System.out.println("add.......");
        return a+b;
    }
    @Override
    public String update(String id) {
        System.out.println("update===========");
        return id;
    }
}

(2)创建UserDao的代理对象,调用增强方法
需要注意:InvocationHandler接口里有invoke方法必须实现,而调用代理对象的任何方法,实质都是在执行invoke方法。           

public class JDKProxy {
    public static void main(String[] args) {
/**
newProxyInstance的三个内容:类加载器、要实现的接口的class、
和InvocationHandler(这是个接口,里面写的增强类的具体逻辑)
*/
        Class[] interfaces = {UserDao.class};
        UserDaoImpl userDao = new UserDaoImpl();
        UserDao dao = (UserDao) Proxy.newProxyInstance(
                JDKProxy.class.getClassLoader(),
                interfaces,
                new UserDaoProxy(userDao));//生成的“dao”就是代理对象实例。
        //也可以直接用匿名内部类的方法来写(new InvocationHandler)

        int add = dao.add(1, 2);//使用代理对象dao调用add的时候,无需改变add源码,却增强了功能。
        System.out.println("add=" + add);
    }
}

//创建代理对象代码
class UserDaoProxy implements InvocationHandler {
    //把创建的是谁的代理对象,把谁传递过来
    //有参数构造传递
    private Object obj;//要创建obj的代理对象
    public UserDaoProxy(Object obj) {
        this.obj = obj;
    }
    //增强的逻辑:InvocationHandler接口里有invoke方法必须实现
//调用代理对象的任何方法,实质都是在执行invoke方法。
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //方法之前(增强)
        System.out.println("方法之前执行...."+method.getName()+" :传递的参数..." + Arrays.toString(args));
        //被增强的方法执行(原模块功能不变)
        Object res = method.invoke(obj, args);//res=3
        //方法之后(增强)
        System.out.println("方法之后执行...."+obj);
        return res;
    }
}

        但是有个遗留问题,invoke函数究竟是如何被调用的,往下看了源码也没有分析出来,个人推测是这样的:

        因为传入的obj其实就是要动态代理的原对象,但我们不知道具体执行什么方法,此时dao还未调用add方法。但调用了以后,invoke方法却能够自动调用、增强方法,内部应该是采用反射的方法,拿到“add”这个方法名称,通过getMethod反射出方法的类对象,再用method.invoke(具体对象)来实现方法的调用,从而调用add,并完成前后的增强。

1.2 cglib:基于父类的动态代理技术。

        方法:为目标对象动态地生成子对象,其具有了父类的方法(实际不是继承)
        实现类似,此处不做代码示例。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/904469.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Dockerfile部署LNMP

文章目录 一、项目模拟1. 项目环境2. 服务器环境3. 任务需求 二、Linux 系统基础镜像三、Nginx1. 建立工作目录2. 编写 Dockerfile 脚本3. 准备 nginx.conf 配置文件4. 生成镜像5. 创建自定义网络6. 启动镜像容器7. 验证 nginx 三、Mysql1. 建立工作目录2. 编写 Dockerfile3. 准…

CompletableFuture总结和实践

CompletableFuture被设计在Java中进行异步编程。异步编程意味着在主线程之外创建一个独立的线程,与主线程分隔开,并在上面运行一个非阻塞的任务,然后通知主线程进展,成功或者失败。 一、概述 1.CompletableFuture和Future的区别&…

Centos7查看磁盘和CUP统计信息iostat命令

Centos7查看磁盘和CUP统计信息iostat命令 Centos7内存高|查看占用内存命令 docker实战(一):centos7 yum安装docker docker实战(二):基础命令篇 docker实战(三):docker网络模式(超详细) docker实战(四):docker架构原理 docker实战(五):docker镜像及仓库配置 docker实战(六…

Interlij IDEA 运行 ruoyi 后端项目。错误: 找不到或无法加载主类 com.ruoyi.auth.RuoYiAuthApplication

错误: 找不到或无法加载主类 com.ruoyi.auth.RuoYiAuthApplication 用了 IDEA运行,参考以下issue删除.idea目录也没有用 (官方文档写是用Eclipse运行) 错误: 找不到或无法加载主类 com.ruoyi.auth.RuoYiAuthApplication Issue #I48N2X 若依/RuoYi-C…

Seaborn数据可视化(二)

目录 1.Seaborn风格设置 1.1 主题设置 1.2 轴线设置 1.3 移除轴线 1.4 使用字典传递函数 2.设置绘图元素比例 2.1 设置绘图元素比例paper 2.2 设置绘图元素比例poster 2.3 设置绘图元素比例notebook Seaborn将Matplotlib的参数划分为两个独立的组合,第一组用于…

关于Coursera网站视频无法观看

文章目录 前言找Ip 改hosts验证 前言 众所周知,coursera是很不错的学习网站,但由于国内访问限制,导致我的学习之路举步维艰 在科学上网彻底崩盘后,终于断了我的学习热情(真的很想骂人) 网站只能登入&#…

Qt6之如何为QDialog添加最大化和最小化按钮

在QDialog构造函数中添加以下几行代码: // 设置窗体最大化和最小化Qt::WindowFlags windowFlag Qt::Dialog;windowFlag | Qt::WindowMinimizeButtonHint;windowFlag | Qt::WindowMaximizeButtonHint;windowFlag …

No115.精选前端面试题,享受每天的挑战和学习

文章目录 变量提升和函数提升的顺序Event Loop封装 FetchAPI,要求超时报错的同时,取消执行的 promise(即不继续执行)强缓存和协商缓存的区别token可以放在cookie里吗? 变量提升和函数提升的顺序 在JavaScript中&#…

Cesium之水流模型

关于Primitive。 Primitive和Entity,一般翻译成图元和实体,图元更接近底层,实体是封装后的高级对象,使用更加简便。一般来说,Primitive的使用相对繁琐,相比Entity需要使用者自己初始化更多对象&#xff0c…

LabVIEW开发血液动力学监测仪

LabVIEW开发血液动力学监测仪 心电图和光电容积描记图的缩写分别是心电图、心电图和PPG。都熟悉“心脏病发作”、“心力衰竭”、“冠状动脉疾病”和“中风”等术语,但中很少有人意识到这些疾病都被认为是心血管疾病。心脏病学是一个医学领域,专注于心脏…

树莓牌4B安装Centos8

准备工作 镜像:https://people.centos.org/pgreco/CentOS-Userland-8-stream-aarch64-RaspberryPI-Minimal-4/ 烧制工具:https://www.raspberrypi.com/software/ 初始化 将上述工具烧制好的SD卡插入树莓派,通电。通过网线将树莓派与电脑连…

回归预测 | MATLAB实现PSO-RBF粒子群优化算法优化径向基函数神经网络多输入单输出回归预测(多指标,多图)

回归预测 | MATLAB实现PSO-RBF粒子群优化算法优化径向基函数神经网络多输入单输出回归预测(多指标,多图) 目录 回归预测 | MATLAB实现PSO-RBF粒子群优化算法优化径向基函数神经网络多输入单输出回归预测(多指标,多图&a…

C++初阶——string(字符数组),跟C语言中的繁琐设计say goodbye

前言:在日常的程序设计中,我们会经常使用到字符串。比如一个人的身份证号,家庭住址等,只能用字符串表示。在C语言中,我们经常使用字符数组来存储字符串,但是某些场景(比如插入,删除)下操作起来很…

在线HmacSHA256加密工具--在线获取哈希值又称摘要

具体请前往: 在线计算HmacSha256工具

【Unittest】Unittest接口测试框架开发-以登录模块为例

文章目录 框架结构框架目录结构封装被测试系统接口定义接口测试用例集成测试报告测试数据参数化(一)分析与数据构造(二)基于JSON实现参数化(三)基于数据库实现参数化 框架结构 框架结构包括:被…

Stable Diffusion:使用自己的数据集微调训练LoRA模型

Stable Diffusion:使用自己的数据集微调训练LoRA模型 前言前提条件相关介绍微调训练LoRA模型下载kohya_ss项目安装kohya_ss项目运行kohya_ss项目准备数据集生成关键词模型参数设置预训练模型设置文件夹设置训练参数设置 开始训练LoRA模型TensorBoard查看训练情况 测…

[JAVAee]Tomcat - Servlet

目录 Tomcat Servlet的工作 创建Servlet ①项目 ②依赖 ③目录 ④代码 ⑤打包 ⑥部署 ⑦验证 Servlet的运行原理 Servlet API HttpServlet 方法 处理Get/POST请求 HttpServletRequest 方法 获取请求中的信息 获取GET请求中的参数 获取POST请求中的参数…

基于YOLOv8模型和PCB电子线路板缺陷目标检测系统(PyTorch+Pyside6+YOLOv8模型)

摘要:基于YOLOv8模型PCB电子线路板缺陷目标检测系统可用于日常生活中检测与定位PCB线路板瑕疵,利用深度学习算法可实现图片、视频、摄像头等方式的目标检测,另外本系统还支持图片、视频等格式的结果可视化与结果导出。本系统采用YOLOv8目标检…

Dbeaver安装与报错解决方案

官网 https://dbeaver.io/ Dbeaver :社区版,开源免费。 下载 下载地址(官网下载不了,在GitHub下载): https://github.com/dbeaver/dbeaver/releases 安装过程中的问题 双击安装包,按照提示…

第7步---MySQL的视图操作和

第7步---MySQL的视图操作 虚拟表。保存的只是视图的定义。不存放真实的数据,数据还是在原先的表中。 好处是方便和简化代码以及安全。 1.视图创建 数据准备 -- 创建表的测试数据 create table dept(deptno int primary key,dname varchar(20),loc varchar(20) ); …