很难出错的spring5(六)—— AOP预备知识:静态代理和动态代理
一、静态代理在学习多线程的时候我们学过静态代理new Thread(new 线程类()).start()的原理就是静态代理。在线程类的run方法里面我们只写了和线程无任何关系的简单逻辑new一个对象丢给Thread对象就能跑起来了如何创建的线程如何实现CPU调度线程转为执行状态都是Thread对象帮我们做的。https://blog.csdn.net/qq_44886213/article/details/127648846缺点一个真实对象就要产生一个代理对象例如要开3个线程就要new出来3个Thread对象二、动态代理首先静态代理的优点动态代理全都有并且修正了其缺点。一个代理对象直接代理一个接口可以代理多个类只要类实现了这个接口就行。1. springAOP的机制是动态代理动态代理的机制是反射,这也是动态代理难以理解的地方。2. 代理类是Proxy.newProxyInstance() 动态生成的不是我们直接写好的3. 动态代理分为两大类基于接口的动态代理基于类的动态代理基于接口JDK 原生动态代理我们学这个基于类cglibjava字节码实现javasist需要了解两个类java.lang.reflect.Proxy类静态方法Proxy.newProxyInstance() 动态生成一个代理实例java.lang.reflect.InvocationHandler接口调用处理程序要重写invoke方法2.1 例子接口定义增删改查4个抽象方法package com.kuang.service; /** * 业务接口 */ public interface IService { void add(); void delete(); void modify(); void search(); }接口实现类一增删改查春晚小品的业务类package com.kuang.service; /** * 增删改查春晚小品的业务类 */ public class ComedyServiceImpl implements IService{ public void add() { System.out.println(增加一个春晚小品); } public void delete() { System.out.println(删除一个春晚小品); } public void modify() { System.out.println(修改一个春晚小品); } public void search() { System.out.println(查找一个春晚小品); } }接口实现类二增删改查春晚歌曲的业务类package com.kuang.service; /** * 增删改查春晚歌曲的业务类 */ public class SongServiceImpl implements IService{ public void add() { System.out.println(增加一个春晚歌曲); } public void delete() { System.out.println(删除一个春晚歌曲); } public void modify() { System.out.println(修改一个春晚歌曲); } public void search() { System.out.println(查找一个春晚歌曲); } }InvocationHandler的实现类可以看作动态代理的模板package com.kuang.service; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; /** * 处理类的【模板】 */ public class MyInvocationHandler implements InvocationHandler { //1.被代理的角色的接口 IService target; public void setService(IService target) { this.target target; } //2.动态生成代理对象 public Object getProxy(){ return Proxy.newProxyInstance(this.getClass().getClassLoader(),target.getClass().getInterfaces(),this); } //3.处理代理对象并返回结果 public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { Object result method.invoke(target, args); return result; } //4.代理自己要干的一系列事情写在这里 }客户端package com.kuang.service; import java.lang.reflect.Method; public class Client { public static void main(String[] args) { ComedyServiceImpl comedyService new ComedyServiceImpl(); MyInvocationHandler handler new MyInvocationHandler(); //设置被代理的真实角色 handler.setService(comedyService); //动态生成代理对象 IService proxy (IService) handler.getProxy(); proxy.add(); //---调用invoke proxy.delete(); proxy.modify(); proxy.search(); System.out.println(------------------); SongServiceImpl songService new SongServiceImpl(); //设置被代理的真实角色 handler.setService(songService); //动态生成代理对象 proxy (IService) handler.getProxy(); //这不也是重新new了一个代理对象吗 proxy.add(); proxy.delete(); proxy.modify(); proxy.search(); } }考虑一个问题使用动态代理如果要增加一个打印日志业务怎么加呢应该把增加的业务写在InvocationHandler实现类MyInvocationHandler的invoke方法里。我们依然调用add(方法但是多做了两件事情。三、静态代理、动态代理、AOP串讲AOP原理是spring的一个功能。多个接口都需要加日志、事务、校验时避免打开每一个接口去塞进去可以采用切入的方式像插入一个切片一样就很形象。切入点可以细化到什么程度spring AOP的话只能细化到方法执行层面因为spring AOP是靠动态代理实现的它的连接点只有“方法执行”就是你记得Pointcut(execution(* com.bob.pdf.controller..*.*(..)))也能看出只能细化到方法层面如果是java原生JDK可以再细化到方法里面。AOP底层原理是动态代理动态代理的底层用的是反射反射就是用Class类获取类的实例Class c1就相当于你自己在开发环境里打开了这个类的.class文件能看到这个类的成员变量和成员方法一样c1也能获得反射是通过注解去触发的——注解不就是写给程序编译器、虚拟机看的吗Retention定义了注解的生命周期override、Data这些注解是编译时有效是写给编译器看的像框架用到的注解都是运行时有效的是写给JVM虚拟机看的。虚拟机看到Before()此类注解就知道要切入了往那切呢就会去找Before()对应的Pointcut。静态代理的话要给每种实现类都单独写一个静态代理。比如说我需要日志的静态代理系统里有User接口以及User接口的一系列实现类SimpleUser、VIPUser有Order接口以及Order接口的一系列实现类预订单Order、普通订单Order、退单Order。在用户业务、订单业务我都想插入日志的话那我就要写两个静态代理Proxy因为每个Proxy只能维护一种业务类型的接口嘛。用户业务日志代理类//1.接口 interface IUserService{ 用户相关业务01(); 用户相关业务02(); } //2.接口实现类-普通用户业务 Class SimpleUserServiceImpl implements IUserService{ Override 用户相关业务01(){ ..... } Override 用户相关业务02(){ ..... } } //3.接口实现类-VIP用户业务 Class VIPUserServiceImpl implements IUserService{ Override 用户相关业务01(){ ..... } Override 用户相关业务02(){ ..... } } //4. 静态代理类 UserProxy{ IUserService userService; //缺点1每个Proxy只能维护一种业务类型的接口 UserProxy(IUserService userService){this.userService userService;} //缺点2要重写接口的方法 Override 订单相关业务01(){ log.info(---一些业务前的日志----); userService.用户相关业务01(); log.info(---一些业务后的日志----); } Override 订单相关业务02(){ log.info(---一些业务前的日志----); userService.用户相关业务02(); log.info(---一些业务后的日志----); } } //5.使用 public class StaticProxyUserTest { public static void main(String[] args) { IUserService target new SimpleUserServiceImpl(); UserProxy proxy new UserProxy(target); proxy.用户相关业务01(); proxy.用户相关业务02(); } }订单实现日志的话还要再写一个代理//1.接口 interface IOrderService{ 订单相关业务01(); } //2.接口实现类-预订单业务 Class BookOrderServiceImpl implements IOrderService{ Override 订单相关业务01(){ ..... } } //3.接口实现类-普通订单业务 Class SimpleOrderServiceImpl implements IOrderService{ Override 订单相关业务01(){ ..... } } //4.接口实现类-退单业务 Class ReturnOrderServiceImpl implements IOrderService{ Override 订单相关业务01(){ ..... } } //5. 静态代理类 OrderProxy{ IOrderService order; //缺点1每个Proxy只能维护一种业务类型的接口 OrderProxy(IOrderService order){this.order order;} //缺点2要重写接口的方法 Override 订单相关业务01(){ log.info(---一些业务前的日志----); order.订单相关业务01(); log.info(---一些业务后的日志----); } } //6.使用那你可能会去想Proxy里维护接口的变量我写成Object类型给他整成通用的不就行了都可以共用同一个Proxy了首先恭喜你解锁了一点点动态代理的东西。但是别忘了静态代理要重写业务的业务你咋重写业务可没法大家都抽象成doSomething啊所以静态代理只能老老实实写两个Proxy。所以静态代理就是要写好多个Proxy而且每个Proxy代理类里都要重写业务方法。这就要求目标类必须要有个接口因为代理类要实现这个接口嘛这是静态代理最麻烦的三个地方。动态代理如何解决如上三个弊端呢我们先讲JDK原生动态代理先不看注解实现的一步步来嘛。JDK原生动态代理解决这俩弊端的其中一个方法已经被你解锁了就是维护Object类型的成员变量这样就可以承接所有类型了。那业务怎么通用呢反射——InvocationHandler的invoke方法。针对第三个弊端。动态代理分两种JDK 动态代理依然强制要求目标对象必须实现接口。如果是CGLIBCGLIB无需接口比如我想在方法之前打印方法名只需要写一个日志处理器可代理任何接口//日志处理器 public class LogHandler implements InvocationHandler { private Object target; // 1、可以代理任意类型 public LogHandler(Object target) { this.target target; } Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { System.out.println(开始调用 method.getName()); Object result method.invoke(target, args); // 2、反射调用真实方法 return result; } } //使用 public class Main { public static void main(String[] args) { UserService userService new UserServiceImpl(); // Proxy.newProxyInstance动态生成代理对象 UserService proxy (UserService) Proxy.newProxyInstance( userService.getClass().getClassLoader(), userService.getClass().getInterfaces(), new LogHandler(userService) ); proxy.addUser(李四); } }使用的时候跟静态代理一样。弊端是我如果要给某个方法加日志还是要调用这个方法之前手动去写new proxy然后proxy.调用方法无法满足对修改关闭。所以有了AOP。有了spring注解以后更简单了。被代理的可以自动注入不用向上面一样手动set了也不用手动new Proxy代理类了你只需要关注如何写这个切面类以及切面方法就好了。当然也有弊端就是没有Java原生JDK那么灵活用spring实现的动态代理joinpoint只能是方法执行的时候。Aspect //声明这是一个切面类 Component //让Spring管理它 public class LogAspect { // 切点匹配 service 包下所有类的所有方法可精确到具体类 Pointcut(execution(* com.example.service..*.*(..))) public void serviceLayer() {} // 环绕通知覆盖原 LogHandler 的 invoke 逻辑 Around(serviceLayer()) public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable { String methodName joinPoint.getSignature().getName(); System.out.println(【Spring AOP】日志开始调用 methodName); Object result joinPoint.proceed(); // 执行真实方法 System.out.println(【Spring AOP】日志 methodName 调用完成); return result; } }

相关新闻

FunASR无障碍服务:3步搭建实时字幕系统,为听障人士打造沟通桥梁

FunASR无障碍服务:3步搭建实时字幕系统,为听障人士打造沟通桥梁

FunASR无障碍服务:3步搭建实时字幕系统,为听障人士打造沟通桥梁 【免费下载链接】FunASR Open-source speech recognition toolkit for training, inference, streaming ASR, VAD, punctuation, speaker diarization pipelines, and OpenAI-compatible/M…

2026/7/27 17:21:57 阅读更多 →
C语言常见面试题汇总

C语言常见面试题汇总

目录题1:变量的声明和定义有什么区别题2:写出bool 、int、 float、指针变量与“零值”比较的if语句题3:sizeof和strlen的区别题4:C中的malloc和C++中的new有什么区别题5:…

2026/7/27 17:21:57 阅读更多 →
Windows安全攻防实战:从权限模型到漏洞利用与纵深防御

Windows安全攻防实战:从权限模型到漏洞利用与纵深防御

1. 项目概述:从权限到漏洞的Windows安全攻防全景在Windows系统的日常运维、渗透测试或安全加固工作中,我们常常会陷入一个误区:要么只关注某个具体的漏洞利用工具,要么只死记硬背几条安全策略。但真正的系统安全,是一个…

2026/7/27 17:21:57 阅读更多 →

最新新闻

Jellium Desktop界面动画性能测试:测量动画性能

Jellium Desktop界面动画性能测试:测量动画性能

Jellium Desktop界面动画性能测试:测量动画性能 【免费下载链接】jellium-desktop An unofficial desktop client for Jellyfin 项目地址: https://gitcode.com/GitHub_Trending/je/jellium-desktop Jellium Desktop作为一款非官方的Jellyfin桌面客户端&…

2026/7/27 17:36:05 阅读更多 →
合规可控、查重无忧:5 款 AI 论文辅助工具深度测评,解锁学术写作效率与质量双提升

合规可控、查重无忧:5 款 AI 论文辅助工具深度测评,解锁学术写作效率与质量双提升

当下高校对学术诚信、AI 内容溯源、重复率管控日趋严格,不少毕业生和科研人员陷入两难:纯手动撰写耗时耗力,普通 AI 工具又存在查重飘红、AI 痕迹过重、内容逻辑生硬、稿件泄露等风险,极易被导师质疑学术规范性。真正靠谱的论文 A…

2026/7/27 17:36:05 阅读更多 →
AI写论文,如何做到合规、查重安全、导师不质疑?这5款工具给出了答案

AI写论文,如何做到合规、查重安全、导师不质疑?这5款工具给出了答案

毕业季的“论文急诊室”年年开张,只是今年的“急诊项目”换了新花样。传统“查重率”的焦虑还没消散,“AIGC疑似率”这枚新核弹,直接把无数学子的毕业梦炸得外焦里嫩。好不容易用各种AI工具把查重率压到15%以内,结果打开检测报告&…

2026/7/27 17:36:05 阅读更多 →
Jellium Desktop皮肤社区指南:参与皮肤社区

Jellium Desktop皮肤社区指南:参与皮肤社区

Jellium Desktop皮肤社区指南:参与皮肤社区 【免费下载链接】jellium-desktop An unofficial desktop client for Jellyfin 项目地址: https://gitcode.com/GitHub_Trending/je/jellium-desktop Jellium Desktop是一款非官方的Jellyfin桌面客户端&#xff0c…

2026/7/27 17:36:05 阅读更多 →
MagicScaler源码解析:核心算法与架构设计

MagicScaler源码解析:核心算法与架构设计

MagicScaler源码解析:核心算法与架构设计 【免费下载链接】PhotoSauce MagicScaler high-performance, high-quality image processing pipeline for .NET 项目地址: https://gitcode.com/gh_mirrors/ph/PhotoSauce MagicScaler是一个为.NET平台打造的高性能…

2026/7/27 17:36:05 阅读更多 →
硬件工程师必读:EVM评估模块的安全、合规与实战应用指南

硬件工程师必读:EVM评估模块的安全、合规与实战应用指南

1. 评估模块的本质:研发工程师的“探路石”在任何一个硬件项目的早期,当你在数据手册上看到一颗芯片的参数时,心里总会有些打鼓:它的实际性能真如纸面描述那般完美吗?它的热特性在满载时能否扛得住?外围电路…

2026/7/27 17:35:05 阅读更多 →

日新闻

【JAVA毕设源码分享】基于SpringBoot的社区智能垃圾管理系统的设计与实现(程序+文档+代码讲解+一条龙定制)

【JAVA毕设源码分享】基于SpringBoot的社区智能垃圾管理系统的设计与实现(程序+文档+代码讲解+一条龙定制)

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围:&am…

2026/7/27 0:00:54 阅读更多 →
SPI实战指南:从时钟模式到寄存器配置,解决嵌入式通信难题

SPI实战指南:从时钟模式到寄存器配置,解决嵌入式通信难题

1. 项目概述:从寄存器手册到实战指南 如果你手头有一份类似德州仪器(TI)TMS320x240xA系列DSP的SPI模块技术手册,看着里面密密麻麻的寄存器位定义、时序图和公式,是不是感觉头大?这份资料虽然权威&#xff0…

2026/7/27 0:00:54 阅读更多 →
【JAVA毕设源码分享】基于springboot的水果购物管理系统的设计与实现(程序+文档+代码讲解+一条龙定制)

【JAVA毕设源码分享】基于springboot的水果购物管理系统的设计与实现(程序+文档+代码讲解+一条龙定制)

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围:&am…

2026/7/27 0:00:54 阅读更多 →

周新闻

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 道路桥梁裂缝检测数据集 道路桥梁病害识别检测数据集

深度学习道路桥梁裂缝检测系统 数据集6000张 完整源码已标注数据集训练好的模型环境配置教程程序运行说明文档,可以直接使用!系统支持图片、视频、摄像头等多种方式检测裂缝,功能强大实用。 1数据集6000张 8各类别

2026/7/27 4:33:59 阅读更多 →
深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

深度学习YOLO模型如何训练 PUBG 绝地求生目标检测数据集

pubg数据集 精选原图1.42万数据 1.49万标签 无任何重复、算法增强或冗余图像! pubg绝地求生目标检测数据集 1分类:e_body,14905个标签,txt格式 共计14244张图,99%为640*640尺寸图像 适合yolo目标检测、AI训练关键词&am…

2026/7/27 6:31:56 阅读更多 →
Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

Apex检测数据集数据集详情检测类别: allies enemy tag图片总量:7247张训练集:5139张验证集:1425张测试集:683张标注状态:全部已标注,即拿即用数据格式:支持YOLO格式及其他格式&#…

2026/7/27 4:01:12 阅读更多 →

月新闻