【Spring】代理模式——动态代理

1、基本概念

  • 动态代理允许我们在运行时根据指定的接口动态地创建代理对象,这个代理对象与目标对象实现了相同的接口,因此可以完全替代目标对象执行相同的操作。
  • 通过动态代理,我们可以在不修改目标对象代码的情况下,为目标对象添加额外的功能或逻辑。
  • JDK动态代理和CGLIB动态代理是Java中两种常见的动态代理实现方式,它们各自有不同的特点和适用场景。

2、原理

  • 动态代理的实现原理主要基于Java的反射机制。
  • 在运行时,动态代理会根据指定的接口创建一个代理类,并在代理类中重写接口中的所有方法。
  • 当代理对象调用接口方法时,实际执行的是代理类中的对应方法。
  • 在代理类中,我们可以通过反射机制调用目标对象的方法,并在执行前后添加自己的逻辑。

3、应用场景

  • 动态代理在Spring框架中得到了广泛应用,主要用于实现AOP(面向切面编程)功能。
  • AOP是一种编程范式,用于处理系统中散布于各个模块之间的交叉关注点问题,如事务管理、日志记录、安全控制等。
  • 通过动态代理,Spring可以在运行时为目标对象创建代理对象,并在代理对象中织入切面逻辑,从而实现对这些交叉关注点问题的统一处理。

4、常见实现方式

4.1  JDK动态代理

4.1.1简介

  • JDK动态代理是Java标准库提供的一种动态代理实现方式,它基于Java的反射机制。
  • JDK动态代理只能代理实现了接口的类,通过动态生成代理类来实现对目标对象的代理。
  • 在JDK动态代理中,代理类是由Java运行时环境动态生成的,每个代理类都会实现与被代理对象相同的接口。
  • 通过使用ProxyMethodInvocationHandler类库来完成动态代理
  • JDK动态代理的优点是简单易用,因为它是Java标准库的一部分,无需引入额外的依赖。

4.1.2代码示例

步骤1:先创建UserService接口

public interface UserService {
void save();
void delete();
}

步骤2:创建一个接口的实现类UserServiceImpl(目标类对象)

public class UserServiceImpl implements UserService {
@Override
public void save() {
System.out.println("主业务逻辑:增加用户管理");
}
@Override
public void delete() {
System.out.println("主业务逻辑:删除用户管理");
}
}

步骤3:创建动态代理(InvocationHandler接口的实现类)

public class MyInvocationHandler implements InvocationHandler {
private Object obj;
public MyInvocationHandler(Object obj){
this.obj=obj;
}
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws
Throwable {System.out.println("开始监控系统...");
long t1 = System.currentTimeMillis();//当前时间
try {
Thread.sleep((int) (Math.random() * 2000));
} catch (InterruptedException e) {
e.printStackTrace();
}
Object o = method.invoke(obj, args);
long t2 = System.currentTimeMillis();//当前时间
System.out.println("结束监控系统...");
System.out.println("一共耗费了" + (t2 - t1) + "毫秒");
//加日志处理
System.out.println(LocalDate.now() + "访问系统");
return o;
}
}

步骤4:使用Proxy,创建代理对象

public class ProxyUtil {
public static Object getProxy(Object target, InvocationHandler handler)
{
return Proxy.newProxyInstance(target.getClass().getClassLoader(),
target.getClass().getInterfaces(), handler);
}
}

步骤5:测试

public static void main(String[] args) {
UserService service= new UserServiceImpl();
UserService proxy = (UserService) ProxyUtil.getProxy(service,
new MyInvocationHandler(service));
proxy.save();
System.out.println("------------------------------------");
proxy.delete();
}
}

4.2  CGLIB动态代理

4.2.1简介

  • CGLIB(Code Generation Library)是一个强大的、高性能的代码生成库,它可以扩展Java类和实现Java接口。
  • 与JDK动态代理不同,CGLIB动态代理是通过继承目标类来创建代理对象的,因此它可以代理没有实现接口的类。
  • CGLIB动态代理底层使用ASM(一个Java字节码操控和分析框架)来操作字节码生成新的类,为对象引入间接级别,以控制对象的访问。
  • CGLIB动态代理的优点在于它可以代理没有实现接口的类,提供了更多的灵活性。
  • CGLIB动态代理不能对final类及final方法进行代理。

4.2.2代码示例

步骤1:创建目标类

public class AccountService {
public void save(){
System.out.println("保存账务管理业务");
}
public void pay(){
System.out.println("支持管理业务");
}
}

步骤2:编写增强类

public class MyInterceptor implements MethodInterceptor {
private Object obj;
public MyInterceptor(Object obj) {
this.obj = obj;
}
@Override
public Object intercept(Object o, Method method, Object[] objects,
MethodProxy methodProxy) throws Throwable {
System.out.println("进入系统");
Object invoke = method.invoke(obj, objects);
System.out.println(LocalDate.now());
return invoke;
}
}

步骤3:测试

public class Test {
public static void main(String[] args) {
AccountService service = new AccountService();
Enhancer enhancer = new Enhancer();
enhancer.setClassLoader(AccountService.class.getClassLoader());
enhancer.setSuperclass(AccountService.class);
enhancer.setCallback(new MyInterceptor(service));
AccountService accountService = (AccountService) enhancer.create();
accountService.save();
System.out.println("------------------------------");
accountService.pay();
}
}

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

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

相关文章

ZISUOJ 数据结构--图及其应用

说明 主要考察建图,图的遍历以及求最小生成树。都还是比较简单的,后面就直接上代码了。 最小生成树采用prim还是kruskal算法要看题目怎么给出数据,如果以邻接矩阵的形式给出,采用prim算法比较合适,如果以边和边的权重的…

盲人社会适应性训练:打开生活的新篇章

在现代社会的快节奏中,每一位成员都在寻求更好的方式来适应环境,对于盲人群体而言,这种适应性尤为关键。盲人社会适应性训练作为一个旨在提升盲人生活质量和独立性的系统性过程,正逐步受到广泛关注。在这一过程中,一款…

轻量SEO分析报告程序网站已开心去授权

轻量SEO分析报告程序网站已开心去授权,可以让你生成有洞察力的、 简洁的、易于理解的SEO报告,帮助你的网页排名和表现更好 网站源码免费下载地址抄笔记 (chaobiji.cn)https://chaobiji.cn/

如何通过软件IIC使用MPU6050陀螺仪

目录 1. MPU6050简介 2. MPU6050参数 3. MPU6050硬件电路 4. 代码编写 4.1 MPU6050写寄存器 4.2 MPU6050读寄存器 4.3 初始化 4.4 MPU6050获取ID号 4.5 MPU6050获取数据 1. MPU6050简介 MPU6050是一个6轴姿态传感器,可以测量芯片自身X、Y、Z轴的…

前端路由原理及hash模式和history模式和Abstract模式

1.前端路由原理: 前端路由的核心在于改变视图的同时不会向后端发出请求,而是去加载路由对应的组件; vue-router是将组件映射到路由,然后在渲染出来,并且实现Hash、History、Abstract这三种模式,一般默认H…

iostat之性能监控

#date 2024年5月23日 #作者:野生老中医 #功能:查找磁盘或者cpu瓶颈,繁忙大于70,队列大于2,等待I/O平均的时间超过10毫秒的脚本 #脚本名称:io.sh #使用方式:sh io.sh #! /bin/bash #1 磁盘模块分析 #在使用IOStat进行系统性能监控时,需要注意综合分析磁盘和CPU等多…

Webpack5 解决静态资源重复打包问题

Webpack5 解决静态资源重复打包问题 在使用url-loader、file-loader时,想将资源打包到特定的文件夹,而不是根目录时,Webpack还是会重复将资源打包到根目录。 解决 {test: /\.(png|svg|jpg|jpeg|gif|ico)$/,use: [{loader: url-loader,option…

点灯yes,关灯no

main.c #include"led.h" //手动封装一个延时函数 void delay_ms(int ms) {int i,j;for(i0;i<ms;i){for(j0;j<2000;j){}} } int strcmp(char *s1,char *s2) {while(*s1&&(*s1*s2)){*s1;*s2;}return *s1-*s2; } int main() {//使能GPIO的外设时钟*((uns…

(delphi11最新学习资料) Object Pascal 学习笔记---第13章

第13章 对象和内存 ​ 本章关注 Object Pascal 语言中一项非常具体且相当重要的主题—内存管理。Object Pascal 语言及其运行时环境提供了一种独特的解决方案&#xff0c;介于 C 风格的手动内存管理和 Java 或 C# 风格的自动垃圾回收之间。 ​ 采用这种介于两者之间的方式在于…

2024-05-23 vscode + clang + clangd 解锁 modules

点击 <C 语言编程核心突破> 快速C语言入门 vscode clang clangd 解锁 modules 前言一、准备二、使用备注: 总结 前言 要解决问题: 昨天解锁VS使用modules, 但是不完美, 没有代码提示和补全了, 今天用 vscode clang clangd 解锁 modules, 同时还有代码补全及提示. …

js中的 map 方法遍历

map方法// map 方法不改变原本的数组 所以要将map之后的值赋值给一个新的变量 // ...item 的作用是 // 将调用 map 函数的数组里的所有数据 都复制到新的&#xff0c;接收map之后的数组中 // 在此基础上 再覆盖或者添加新的数据&#xff0c;如 outpatient 和 recommended 属性/…

​​​【收录 Hello 算法】9.4 小结

目录 9.4 小结 1. 重点回顾 2. Q & A 9.4 小结 1. 重点回顾 图由顶点和边组成&#xff0c;可以表示为一组顶点和一组边构成的集合。相较于线性关系&#xff08;链表&#xff09;和分治关系&#xff08;树&#xff09;&#xff0c;网络关系&#xff08;图&am…

Defog发布Llama-3-SQLCoder-8B,文本转SQL模型,性能比肩GPT-4,准确率超90%,消费级硬件可运行

前言 在计算语言学领域&#xff0c;将自然语言转化为可执行的SQL查询是一个重要的研究方向。这对于让那些没有编程或SQL语法知识的用户也能轻松访问数据库信息至关重要。Defog团队近日发布了基于Llama-3的SQLCoder-8B模型&#xff0c;它在文本转SQL模型领域取得了显著突破&…

2024.05.23 学习记录

1、 react hooks 面经复习 2、xiaolin coding 计算机网络 复习 3、组件库 subMenu、test测试、tabs组件初步开发完成 4、代码随想录刷题&#xff1a;动态规划 01背包 all

MyBatisPlus标准分页功能制作,以及设置分页拦截器,selectPage(new Page<>(current,size),null)

目录 1、设置分页拦截器 2、创建数据库及表 3、pom.xml 4、添加MP的相关配置信息 application.yml 5、根据数据库表创建实体类 User 6、创建 UserDao 接口 7、编写引导类 8、编写测试类 9、Run的运行结果 1、设置分页拦截器 package com.example.config; import com.baomidou.m…

Linux: network: send 失败的时候要不要close socket?

最近遇到一个例子&#xff0c;说有zerowindow出现&#xff1b;出现的原因是接收方的CPU被其他程序吃光&#xff0c;导致socket的read函数处理非常慢。说明接收端的接收缓存不够用。发送端自然而然的要停止发送。 但是如果在接收方的recv buff&#xff0c;以及发送方的send buf…

探索移动云:我的ES与Kibana之旅

目录 引言&#xff1a; 如何免费体验移动云产品 登录并完成实名认证 选择试用ECS云主机 安全组配置 安装Elasticsearch和Kibana 安装Elasticsearch ​编辑安装kibana 测试结果 使用感觉 引言&#xff1a; 移动云技术产品的发展已经取得了巨大的进步。云数融合、A1、大…

解决vite打包只生成了一个css和js文件问题

文章目录 1. 打包遇到的问题2. 问题原因及修改3. 调整后再次打包&#x1f197; 1. 打包遇到的问题 今天整了一个项目&#xff0c;试了下打包&#xff0c;发下打包后只生成了一个css文件&#xff0c;和一个js文件&#xff0c; 这样肯定是不行的&#xff0c;因为这样这个文件的包…

Windows:iHasher-v0.2安装报错Windows 功能 .NET Framework 3.5

一、情景描述 我们从MSDN下载了镜像文件&#xff0c;一般要验证下载文件的HASH值是否与MSDN上发布的一致&#xff0c;确保传出过程中iso文件没有损坏。 MSDN地址&#xff1a;https://msdn.itellyou.cn/ 我从MSDN下载了Hasher工具&#xff0c;进行校验。 但是&#xff0c;安装…

Marker可以快速且准确地将PDF转换为markdown格式。

Marker Marker可以快速且准确地将PDF转换为markdown格式。 支持多种文档类型&#xff08;针对书籍和科学论文进行了优化&#xff09;支持所有语言移除页眉/页脚/其他杂质格式化表格和代码块提取并保存图像以及markdown将大多数方程转换为latex支持在GPU、CPU或MPS上运行 工作…