自己动手写一个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中还有环绕通知但基本上一个道理。写在后面参考文章列表

相关新闻

写小说卡文怎么办?2026年10款写小说软件真实测评与优缺点对比

写小说卡文怎么办?2026年10款写小说软件真实测评与优缺点对比

卡文,绝对是每个网文作者的宿命。为了保住微薄的全勤奖,这几年我几乎试遍了市面上所有的写小说软件。但说实话,踩过的坑比码出的字还多。很多所谓的ai写小说神器,要么写出来的东西一股AI味,前言不搭后语;要…

2026/7/31 18:39:55阅读更多 →
RAG-Anything:企业级多模态检索增强生成框架的5层架构设计与最佳实践

RAG-Anything:企业级多模态检索增强生成框架的5层架构设计与最佳实践

RAG-Anything:企业级多模态检索增强生成框架的5层架构设计与最佳实践 【免费下载链接】RAG-Anything "RAG-Anything: All-in-One RAG Framework" 项目地址: https://gitcode.com/GitHub_Trending/ra/RAG-Anything 在当今企业数字化转型浪潮中&…

2026/7/31 18:37:55阅读更多 →
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:37:55阅读更多 →
Wand-Enhancer终极指南:如何通过开源工具解锁WeMod完整功能

Wand-Enhancer终极指南:如何通过开源工具解锁WeMod完整功能

Wand-Enhancer终极指南:如何通过开源工具解锁WeMod完整功能 【免费下载链接】Wand-Enhancer Advanced UX and interoperability extension for Wand (WeMod) app 项目地址: https://gitcode.com/GitHub_Trending/we/Wand-Enhancer 你是否曾为WeMod免费版的功…

2026/7/31 23:36:02阅读更多 →
Mac视频预览终极指南:3步解锁MKV、AVI等所有格式的完整支持

Mac视频预览终极指南:3步解锁MKV、AVI等所有格式的完整支持

Mac视频预览终极指南:3步解锁MKV、AVI等所有格式的完整支持 【免费下载链接】QuickLookVideo Finder Thumbnails, Quick Look previews, Get Info metadata and previews for most types of audio and video files. 项目地址: https://gitcode.com/gh_mirrors/ql/…

2026/7/31 23:36:02阅读更多 →
如何在iOS应用中快速集成PinterestSegment?5分钟上手教程

如何在iOS应用中快速集成PinterestSegment?5分钟上手教程

如何在iOS应用中快速集成PinterestSegment?5分钟上手教程 【免费下载链接】PinterestSegment A Pinterest-like segment control with masking animation. 项目地址: https://gitcode.com/gh_mirrors/pi/PinterestSegment PinterestSegment是一款为iOS应用打…

2026/7/31 23:36:02阅读更多 →
终端音频可视化终极指南:CAVA入门与完整配置教程

终端音频可视化终极指南:CAVA入门与完整配置教程

终端音频可视化终极指南:CAVA入门与完整配置教程 【免费下载链接】cava Cross-platform Audio Visualizer 项目地址: https://gitcode.com/GitHub_Trending/ca/cava 你是否想过在终端中看到音乐的跳动?CAVA(Console Audio Visualizer …

2026/7/31 23:36:02阅读更多 →
pkNX:Switch宝可梦游戏数据编辑与随机化工具深度解析

pkNX:Switch宝可梦游戏数据编辑与随机化工具深度解析

pkNX:Switch宝可梦游戏数据编辑与随机化工具深度解析 【免费下载链接】pkNX Pokmon (Nintendo Switch) ROM Editor & Randomizer 项目地址: https://gitcode.com/gh_mirrors/pk/pkNX pkNX是一款专为Nintendo Switch平台宝可梦游戏设计的专业级ROM编辑器和…

2026/7/31 23:36:02阅读更多 →
搭建人生聊天系统的SOP的庖丁解牛

搭建人生聊天系统的SOP的庖丁解牛

人生聊天系统,本质是建立一个“持续与自己、他人、现实对话”的反馈系统。很多人的问题不是没有想法,而是: 想法没有整理;情绪没有处理;问题没有拆解;经验没有沉淀。 于是人生像一个:没有日志记…

2026/7/31 23:34:02阅读更多 →
覆盖国产 + 海外 + 开源模型,OpenClaw 2.7.9 Windows/Mac 双端部署详解

覆盖国产 + 海外 + 开源模型,OpenClaw 2.7.9 Windows/Mac 双端部署详解

🔹 工具基础介绍 OpenClaw 是开源生态中一款实用性较强的本地智能工具,凭借本地离线运行、可视化图形操作和任务自动化三大核心特性,赢得了众多用户的青睐。与普通在线对话AI工具不同,它属于能够直接操控本机软硬件的智能数字员工…

2026/7/31 20:44:05阅读更多 →
伺服阀焊完微漏毁整机?精密激光焊接三关锁住高压

伺服阀焊完微漏毁整机?精密激光焊接三关锁住高压

所谓液压伺服阀体的精密激光焊接,是用激光束对阀座壳体(通常为不锈钢或铝合金)进行密封焊接,使阀体在21-35MPa的高压液压油或压缩气体中长期运行而不发生介质泄漏。液压伺服阀是高端液压系统的"大脑"。从航空航天飞行控…

2026/7/31 17:41:43阅读更多 →
D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南

D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南

D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南 【免费下载链接】d2dx D2DX is a complete solution to make Diablo II run well on modern PCs, with high fps and better resolutions. 项目地址: https://gitcode.com/gh_mirrors/d2/d2dx 你是否还在…

2026/7/31 20:44:05阅读更多 →
物理复制比逻辑复制好在哪?数据库复制原理详解

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

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

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

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

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

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

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

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

2026/7/31 0:00:41阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时,发现推理速度只有可怜的 1-2 FPS,而别人的演示视频却能跑到 30 FPS 以上,那么问题很可能不在模型本身,而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后,会直接使用官方示例…

2026/7/31 0:49:33阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一:为什么你需要了解 Coze 和 Dify?如果你对 AI 应用开发感兴趣,但一看到“大模型”、“智能体”、“工作流”这些词就头疼,觉得门槛太高,那这篇文章就是为你准备的。很多开发者,包括我自己&#…

2026/7/31 5:08:18阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会:配图一直是个让人头疼的问题。2026年,AI生图工具已经非常成熟了,但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1:速度之王2026年6月11日&#xff0c…

2026/7/31 16:02:17阅读更多 →