自己动手写一个spring之aop_2
写在前面在这篇文章 中我们已经使得AOP有了雏形但是代理逻辑的执行还是硬编码的如下OverridepublicObjectinvoke(Objectproxy,Methodmethod,Object[]args)throwsThrowable{if(method.getName().equals(doAction)){System.out.println(-----通过jdk动态代理代理了类的doAction方法........);returnmethod.invoke(target,args);}returnnull;}当然这样做呢不能算错但是扩展性就要弱很多了在不同的业务场景中要做的内容不同该怎么办呢本文就一起来把这个问题解决了。1正文对于具体业务方法执行过程的干预我们可以抽象出一个增强的概念即增强业务方法本身的能力如开始没有性能统计的能力通过AOP就能增加这部分能力为此定义一个类似于标记的接口如下packagecom.hc.minispring.web.v7_aop.aop;/** * 切面概念接口更加具象化使用方法拦截器进行增强织入 */publicinterfaceAdvisor{MethodInterceptorgetMethodInterceptor();voidsetMethodInterceptor(MethodInterceptormethodInterceptor);}再来定义一个更加具体的拦截接口代表要通过拦截的方式来增强packagecom.hc.minispring.web.v7_aop.aop;/** * 基于拦截的抽象这里拦截也是一个抽象的概念并不限定于如何拦截 */publicinterfaceInterceptorextendsAdvice{}在定义一个更加具体的基于方法执行拦截的接口/** * 具体的基于方法的拦截也是我们实现AOP方法动态增强织入的关键 */publicinterfaceMethodInterceptorextendsInterceptor{/** * 增强逻辑执行invocation负责执行目标方法 * param invocation * return * throws Throwable */Objectinvoke(MethodInvocationinvocation)throwsThrowable;}当然MethodInterceptor的具体实现类要由用户来指定这里给出一个追踪方法执行过程的实现类以供测试使用当然仅仅是个例子了packagecom.hc.minispring.web.v7_aop.aop;/** * 方法调用追踪 */publicclassTracingInterceptorimplementsMethodInterceptor{publicObjectinvoke(MethodInvocationi)throwsThrowable{System.out.println(即将执行方法 i.getMethod());Objectreti.proceed();System.out.println(执行方法 i.getMethod() 成功*★,°*:.☆(▽)/$:*.°★* 。);returnret;}}为了能够更加明确的表达要做的事情再来定义一个类似于Advice不真正干活的接口Advisor切面抽象出的概念因为对方法执行的拦截就好像拦了一个面一样如下packagecom.hc.minispring.web.v7_aop.aop;/** * 切面概念接口更加具象化使用方法拦截器进行增强织入 */publicinterfaceAdvisor{MethodInterceptorgetMethodInterceptor();voidsetMethodInterceptor(MethodInterceptormethodInterceptor);}可以看出真正干活的还是MethodInterceptor给出实现类/** * 默认实现简单仅仅是维护了方法拦截器信息更多的是Advisor对于功能的表达语义 * 即更加形象化的存在并不做具体的工作 */publicclassDefaultAdvisorimplementsAdvisor{privateMethodInterceptormethodInterceptor;publicDefaultAdvisor(){}publicvoidsetMethodInterceptor(MethodInterceptormethodInterceptor){this.methodInterceptormethodInterceptor;}publicMethodInterceptorgetMethodInterceptor(){returnthis.methodInterceptor;}}接着就来改造现有的类了从生成代理类的FacotryBean入手这里是com.hc.minispring.aop.ProxyFactoryBean,修改如下packagecom.hc.minispring.aop;// .../** * 真正返回代理bean的工厂bean */publicclassProxyFactoryBeanimplementsFactoryBeanObject{// .../** 切面相关内容 **/privateStringinterceptorName;privateAdvisoradvisor;/** 切面相关内容 **/// ...protectedAopProxycreateAopProxy(){// System.out.println(----------createAopProxy for : target --------);// return getAopProxyFactory().createAopProxy(target);// 修改点创建代理类时增加advisor参数用来执行织入的增强逻辑returngetAopProxyFactory().createAopProxy(target,advisor);}// ...OverridepublicObjectgetObject()throwsException{// 修改点初始化切面initializeAdvisor();returngetSingletonInstance();}// 修改点privatesynchronizedvoidinitializeAdvisor(){Objectadvicenull;MethodInterceptorminull;try{// advice (MethodInterceptor) this.beanFactory.getBean(this.interceptorName);// 正常应该从容器中获取但是这里为了走通流程忽略这个次要矛盾了advicenewTracingInterceptor();// } catch (BeansException e) {}catch(Exceptione){e.printStackTrace();}advisornewDefaultAdvisor();// 给切面设置用户给定的方法拦截器即用户自定义的增强逻辑advisor.setMethodInterceptor((MethodInterceptor)advice);}// ...}advisor参数一路传最终传给负责真正干活的代理类JdkDynamicAopProxy,同时修改其逻辑使用methodinterceprot执行增强的织入逻辑packagecom.hc.minispring.aop;// ...publicclassJdkDynamicAopProxyimplementsAopProxy,InvocationHandler{Objecttarget;// 修改点增加切面Advisoradvisor;publicJdkDynamicAopProxy(Objecttarget,Advisoradvisor){this.targettarget;this.advisoradvisor;}OverridepublicObjectgetProxy(){ObjectobjProxy.newProxyInstance(JdkDynamicAopProxy.class.getClassLoader(),target.getClass().getInterfaces(),this);System.out.println(----------创建基于jdk的动态代理类成功 ---------obj);returnobj;}OverridepublicObjectinvoke(Objectproxy,Methodmethod,Object[]args)throwsThrowable{if(method.getName().equals(doAction)){Class?targetClass(target!null?target.getClass():null);// 修改点使用切面执行逻辑MethodInterceptorinterceptorthis.advisor.getMethodInterceptor();MethodInvocationinvocationnewReflectiveMethodInvocation(proxy,target,method,args,targetClass);returninterceptor.invoke(invocation);}returnnull;}}先来测试一下conrollerRequestMapping(/hello1746)// public String doTest(String name) {// public String doTest(/*HttpServletRequest request, HttpServletResponse response*/) {publicStringdoTest(/*HttpServletRequest request, HttpServletResponse response*/){System.out.println(action: action.getClass());action.doAction();returnindex;}}运行截至这里源码 。我们继续来优化。在很多时候我们可能只需要在方法执行前进行增强或者是在方法执行后进行增强。当然目前的方式也能够实现但是对于用户来说还是不够简洁并且也不够明确所以我们来进一步进行优化即分别定义执行前后的增强方法执行前后的增强方法执行前后的拦截如下4个接口2个类执行前的增强方法执行前的增强方法执行前的拦截/** * 前置增强 */publicinterfaceBeforeAdviceextendsAdvice{}/** * 方法前置增强 */publicinterfaceMethodBeforeAdviceextendsBeforeAdvice{voidbefore(Methodmethod,Object[]args,Objecttarget)throwsThrowable;}/** * 方法前置拦截器包装方法前置增强 */publicclassMethodBeforeAdviceInterceptorimplementsMethodInterceptor{privatefinalMethodBeforeAdviceadvice;publicMethodBeforeAdviceInterceptor(MethodBeforeAdviceadvice){this.adviceadvice;}OverridepublicObjectinvoke(MethodInvocationmi)throwsThrowable{// 方法执行前插入的逻辑由用户给出具体的实现this.advice.before(mi.getMethod(),mi.getArguments(),mi.getThis());// 目标方法执行returnmi.proceed();}}执行后的增强方法执行后的增强方法执行后的拦截/** * 后置增强 */publicinterfaceAfterAdviceextendsAdvice{}/** * 方法后置增强 */publicinterfaceAfterReturningAdviceextendsAfterAdvice{voidafterReturning(ObjectreturnValue,Methodmethod,Object[]args,Objecttarget)throwsThrowable;}publicclassAfterReturningAdviceInterceptorimplementsMethodInterceptor,AfterAdvice{privatefinalAfterReturningAdviceadvice;publicAfterReturningAdviceInterceptor(AfterReturningAdviceadvice){this.adviceadvice;}OverridepublicObjectinvoke(MethodInvocationmi)throwsThrowable{ObjectretValmi.proceed();this.advice.afterReturning(retVal,mi.getMethod(),mi.getArguments(),mi.getThis());returnretVal;}}修改proxyfactorybean的initAdvisor方法privatesynchronizedvoidinitializeAdvisor(){Objectadvicenull;MethodInterceptorminull;try{// advice (MethodInterceptor) this.beanFactory.getBean(this.interceptorName);// 正常应该从容器中获取但是这里为了走通流程忽略这个次要矛盾了// advice new TracingInterceptor();try{// advice new TracingInterceptor();advicenewMethodBeforeAdvice(){Overridepublicvoidbefore(Methodmethod,Object[]args,Objecttarget)throwsThrowable{System.out.println(method: method.getName() before execute***********!!!);}};}catch(Exceptione){e.printStackTrace();}if(adviceinstanceofBeforeAdvice){minewMethodBeforeAdviceInterceptor((MethodBeforeAdvice)advice);}elseif(adviceinstanceofAfterAdvice){minewAfterReturningAdviceInterceptor((AfterReturningAdvice)advice);}elseif(adviceinstanceofMethodInterceptor){mi(MethodInterceptor)advice;}advisornewDefaultAdvisor();advisor.setMethodInterceptor(mi);// } catch (BeansException e) {}catch(Exceptione){e.printStackTrace();}// advisor new DefaultAdvisor();// // 给切面设置用户给定的方法拦截器即用户自定义的增强逻辑// advisor.setMethodInterceptor((MethodInterceptor) advice);}根据不同的类型增强进行不同的处理这里作为测试写死了一个方法前置增强运行测试截至这里源码 。spring中还有环绕通知但基本上一个道理。写在后面参考文章列表

相关新闻

5步打造你的GTA5终极防护盾:YimMenu完整使用指南

5步打造你的GTA5终极防护盾:YimMenu完整使用指南

5步打造你的GTA5终极防护盾:YimMenu完整使用指南 【免费下载链接】YimMenu YimMenu, a GTA V menu protecting against a wide ranges of the public crashes and improving the overall experience. 项目地址: https://gitcode.com/GitHub_Trending/yi/YimMenu …

2026/7/31 18:38:20 阅读更多 →
【单片机课程设计/毕业设计】基于 STM32 的洗衣多流程时序控制方案研究 基于单片机继电器驱动洗衣模拟装置开发(015701)

【单片机课程设计/毕业设计】基于 STM32 的洗衣多流程时序控制方案研究 基于单片机继电器驱动洗衣模拟装置开发(015701)

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

2026/7/31 18:38:20 阅读更多 →
【单片机课程设计/毕业设计】基于嵌入式技术的室内安防多传感一体化监测系统 基于 STM32 的燃气检测温控风扇人体照明控制系统(015601)

【单片机课程设计/毕业设计】基于嵌入式技术的室内安防多传感一体化监测系统 基于 STM32 的燃气检测温控风扇人体照明控制系统(015601)

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

2026/7/31 18:38:20 阅读更多 →

最新新闻

Codex 生成代码不等于交付:用测试和审查识别 AI 编程幻觉

Codex 生成代码不等于交付:用测试和审查识别 AI 编程幻觉

Codex 生成代码不等于交付:用测试和审查识别 AI 编程幻觉 OK,OK,大家好,欢迎大家来到大鹏 AI 教育,我是张大鹏。 AI 编程最危险的时刻,往往不是它明显报错,而是代码看起来非常专业&#xff1a…

2026/7/31 19:23:06 阅读更多 →
Comet与Kodi整合教程:打造家庭影院级流媒体中心

Comet与Kodi整合教程:打造家庭影院级流媒体中心

Comet与Kodi整合教程:打造家庭影院级流媒体中心 【免费下载链接】comet Stremios fastest torrent/debrid search add-on. 项目地址: https://gitcode.com/gh_mirrors/comet40/comet Comet是Stremio最快的种子/解扰搜索插件,通过与Kodi媒体中心整…

2026/7/31 19:23:06 阅读更多 →
生产环境排障与可观测性:后端系统的实战经验汇总

生产环境排障与可观测性:后端系统的实战经验汇总

生产环境排障与可观测性:后端系统的实战经验汇总 一、从告警到根因:生产排障的核心挑战 生产环境排障是后端工程师的必备技能。与开发环境不同,生产环境面临**复杂性(分布式)、高压性(影响用户&#xff0…

2026/7/31 19:23:06 阅读更多 →
LibreCAD工程制图终极指南:7个专业技巧提升标注效率与精度

LibreCAD工程制图终极指南:7个专业技巧提升标注效率与精度

LibreCAD工程制图终极指南:7个专业技巧提升标注效率与精度 【免费下载链接】LibreCAD LibreCAD is a cross-platform 2D CAD program. It can read DXF/DWG, and write DXF/DWG/PDF/SVG files. It supports point/line/circle/ellipse/parabola/hyperbola/spline pr…

2026/7/31 19:23:06 阅读更多 →
Python数据管线与自动化运维工具开发:实战复盘与经验总结

Python数据管线与自动化运维工具开发:实战复盘与经验总结

Python数据管线与自动化运维工具开发:实战复盘与经验总结 一、从手工操作到自动化流水线:Python在工程效率中的关键角色 在过去十年,Python凭借简洁语法、丰富生态、快速原型能力,成为数据工程、自动化运维、DevOps工具链的首选…

2026/7/31 19:23:06 阅读更多 →
AI视频虚拟背景性能瓶颈全拆解:从GPU占用率98%到延迟<120ms的7步调优实录

AI视频虚拟背景性能瓶颈全拆解:从GPU占用率98%到延迟<120ms的7步调优实录

更多请点击&#xff1a; https://intelliparadigm.com 第一章&#xff1a;AI视频虚拟背景性能瓶颈全拆解&#xff1a;从GPU占用率98%到延迟<120ms的7步调优实录 AI视频虚拟背景在Zoom、Teams及自研会议系统中广泛部署&#xff0c;但真实场景下常遭遇GPU持续满载&#xff08…

2026/7/31 19:22:06 阅读更多 →

日新闻

物理复制比逻辑复制好在哪?数据库复制原理详解

物理复制比逻辑复制好在哪?数据库复制原理详解

数据库复制是把主库数据同步到备库的机制&#xff0c;分为逻辑复制和物理复制两种。逻辑复制传输的是 SQL 语句或行变更事件&#xff0c;物理复制传输的是存储引擎底层的物理日志。阿里云 PolarDB&#xff08;云原生数据库&#xff09;采用物理复制&#xff0c;在同步延迟、数据…

2026/7/31 0:00:34 阅读更多 →
BilibiliDown:3分钟学会B站视频下载的终极指南

BilibiliDown:3分钟学会B站视频下载的终极指南

BilibiliDown&#xff1a;3分钟学会B站视频下载的终极指南 【免费下载链接】BilibiliDown (GUI-多平台支持) B站 哔哩哔哩 视频下载器。支持稍后再看、收藏夹、UP主视频批量下载|Bilibili Video Downloader &#x1f633; 项目地址: https://gitcode.com/gh_mirrors/bi/Bilib…

2026/7/31 0:00:34 阅读更多 →
有哪些游戏数据AI平台?游戏行业Data+AI融合方案盘点

有哪些游戏数据AI平台?游戏行业Data+AI融合方案盘点

当前&#xff0c;游戏行业的“DataAI融合”已从概念验证进入价值落地阶段。根据IDC 2025年数据&#xff0c;中国AI游戏云市场规模已达18.6亿元&#xff1b;同时&#xff0c;游戏研发环节AI渗透率高达86%&#xff0c;生成式AI内容普及率超过50%。面对庞大的市场&#xff0c;游戏…

2026/7/31 0:00:34 阅读更多 →

周新闻

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

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

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

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

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

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

2026/7/29 14:34:28 阅读更多 →
Apex英雄目标检测数据集 深度学习框架YOLO如何训练APEX数据集

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

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

2026/7/31 4:19:39 阅读更多 →

月新闻