详细解释动态切入点(DynamicMethodMatcherPointcut)在Spring AOP中的完整处理流程。

核心问题澄清
对于动态切入点,Spring仍然会根据静态匹配的结果创建代理,但代理内部会包含额外的逻辑来处理动态匹配。

让我通过源码级别的解释来详细说明:

Spring AOP 的代理创建流程

  1. 代理创建过程概览
// Spring内部简化逻辑publicclassDefaultAdvisorAutoProxyCreator{publicObjectwrapIfNecessary(Objectbean,StringbeanName){// 1. 找到所有适用的AdvisorList<Advisor>advisors=findEligibleAdvisors(beanClass,beanName);// 2. 为bean创建代理if(!advisors.isEmpty()){returncreateProxy(beanClass,beanName,advisors,targetSource);}returnbean;}}
  1. 静态匹配在代理创建中的作用
// Spring AOP 内部的处理逻辑publicclassAopUtils{publicstaticList<Advisor>findAdvisorsThatCanApply(List<Advisor>advisors,Class<?>clazz){List<Advisor>eligibleAdvisors=newArrayList<>();for(Advisoradvisor:advisors){if(canApply(advisor,clazz)){// 这里调用静态匹配eligibleAdvisors.add(advisor);}}returneligibleAdvisors;}publicstaticbooleancanApply(Advisoradvisor,Class<?>targetClass){Pointcutpc=advisor.getPointcut();// 首先进行静态匹配if(!pc.getClassFilter().matches(targetClass)){returnfalse;}// 获取目标类的所有方法Method[]methods=targetClass.getMethods();for(Methodmethod:methods){// 这里调用静态的matches(Method, Class<?>)方法if(pc.getMethodMatcher().matches(method,targetClass)){returntrue;// 只要有一个方法匹配,就为该类创建代理}}returnfalse;}}
  1. 动态匹配的运行时处理
    当使用DynamicMethodMatcherPointcut时,Spring会创建特殊的MethodInterceptor来支持动态检查:
// Spring内部的动态代理调用链publicclassReflectiveMethodInvocationimplementsMethodInvocation{privateList<Object>interceptorsAndDynamicMethodMatchers;publicObjectproceed()throwsThrowable{// 如果还有拦截器if(this.currentInterceptorIndex==this.interceptorsAndDynamicMethodMatchers.size()-1){// 调用原始方法returninvokeJoinpoint();}ObjectinterceptorOrInterceptionAdvice=this.interceptorsAndDynamicMethodMatchers.get(++this.currentInterceptorIndex);if(interceptorOrInterceptionAdviceinstanceofInterceptorAndDynamicMethodMatcher){// 这是动态切入点!InterceptorAndDynamicMethodMatcherdm=(InterceptorAndDynamicMethodMatcher)interceptorOrInterceptionAdvice;// 执行动态匹配if(dm.methodMatcher.matches(this.method,this.targetClass,this.arguments)){returndm.interceptor.invoke(this);}else{// 动态匹配失败,跳过此通知returnproceed();}}else{// 静态切入点,直接执行return((MethodInterceptor)interceptorOrInterceptionAdvice).invoke(this);}}}

具体示例分析
让我用一个具体的例子来说明:

  1. 示例代码
@ServicepublicclassDataService{publicStringfindById(Longid){System.out.println("执行 findById: "+id);return"Data-"+id;}publicStringfindByName(Stringname){System.out.println("执行 findByName: "+name);return"Data-"+name;}publicvoidsave(Stringdata){System.out.println("执行 save: "+data);}}@ComponentpublicclassAuditPointcutextendsDynamicMethodMatcherPointcut{@Overridepublicbooleanmatches(Methodmethod,Class<?>targetClass){System.out.println("静态匹配检查: "+method.getName());// 只匹配"find"开头的方法returnmethod.getName().startsWith("find");}@Overridepublicbooleanmatches(Methodmethod,Class<?>targetClass,Object...args){System.out.println("动态匹配检查: "+method.getName()+", 参数: "+Arrays.toString(args));// 只对ID大于100的记录进行审计if(method.getName().equals("findById")&&args.length>0){Longid=(Long)args[0];returnid>100;}returnfalse;}}
  1. Spring内部的实际处理流程
// Spring创建代理时的伪代码表示publicclassSpringProxyCreator{publicObjectcreateProxy(Class<?>targetClass,Objecttarget){// 1. 检查AuditPointcut的静态匹配// - 检查findById方法:静态匹配通过// - 检查findByName方法:静态匹配通过// - 检查save方法:静态匹配失败// 2. 为DataService创建代理// 代理会拦截findById和findByName方法returnProxy.newProxyInstance(targetClass.getClassLoader(),targetClass.getInterfaces(),newInvocationHandler(){@OverridepublicObjectinvoke(Objectproxy,Methodmethod,Object[]args){// 对于动态切入点,这里会包含额外的检查逻辑if(method.getName().startsWith("find")){// 这是动态切入点的方法returnhandleDynamicPointcut(method,args);}else{// 其他方法直接调用returnmethod.invoke(target,args);}}privateObjecthandleDynamicPointcut(Methodmethod,Object[]args){// 先检查动态匹配if(auditPointcut.matches(method,targetClass,args)){// 执行审计通知System.out.println("【审计开始】");Objectresult=method.invoke(target,args);System.out.println("【审计结束】");returnresult;}else{// 动态匹配失败,直接执行原方法returnmethod.invoke(target,args);}}});}}
  1. 运行时的实际调用流程
publicclassTest{publicstaticvoidmain(String[]args){ApplicationContextcontext=...;DataServicedataService=context.getBean(DataService.class);// 情况1: findById(50) - 静态匹配通过,动态匹配失败// 代理会拦截,执行动态检查,不执行通知dataService.findById(50L);// 情况2: findById(150) - 静态匹配通过,动态匹配通过// 代理会拦截,执行动态检查,执行通知dataService.findById(150L);// 情况3: findByName("test") - 静态匹配通过,动态匹配失败// 代理会拦截,执行动态检查,不执行通知dataService.findByName("test");// 情况4: save("data") - 静态匹配失败// 代理不会拦截,直接调用原方法dataService.save("data");}}

内存和性能影响

  1. 代理对象的内存布局
// 对于动态切入点的代理对象publicclassDynamicPointcutProxy{// 包含:// 1. 目标对象的引用// 2. 动态切入点的引用// 3. 通知(Advice)的引用// 4. 拦截器链(包含动态匹配逻辑)// 比普通代理多存储的信息:// - 动态匹配的检查逻辑// - 运行时参数的处理逻辑}
  1. 性能对比
// 性能测试示例@SpringBootTestclassPerformanceTest{@TestvoidtestPerformance(){longstart,end;// 测试动态切入点start=System.nanoTime();for(inti=0;i<1000000;i++){dataService.findById((long)i);// 每次调用都执行动态匹配}end=System.nanoTime();System.out.println("动态切入点耗时: "+(end-start)/1000000+" ms");// 测试静态切入点(对比)start=System.nanoTime();for(inti=0;i<1000000;i++){dataService.save("data");// 直接调用,无动态检查}end=System.nanoTime();System.out.println("静态切入点耗时: "+(end-start)/1000000+" ms");}}

核心要点总结

  1. 动态切入点的代理创建规则
    基于静态匹配创建代理:只要matches(Method, Class<?>)返回true的方法,都会被代理

代理包含动态检查逻辑:代理对象内部会包含对动态匹配的检查

运行时决定是否执行通知:每次调用时执行动态匹配,决定是否触发通知

  1. 代理的结构差异
// 静态切入点代理(StaticMethodMatcherPointcut)静态切入点代理{目标对象引用 拦截器链(直接执行通知)}// 动态切入点代理(DynamicMethodMatcherPointcut)动态切入点代理{目标对象引用 动态切入点引用 拦截器链(包含动态检查逻辑+通知)}
  1. 实际代码执行路径
// 调用动态切入点方法的执行路径1.代理对象.invoke()2.检查是否是动态切入点方法(静态匹配已通过) ↓3.执行动态匹配:matches(method,targetClass,args)4.如果匹配通过 → 执行通知 → 执行原方法 ↓5.如果匹配失败 → 直接执行原方法
  1. 重要设计原则
    代理最小化原则:Spring只代理需要代理的方法,而不是整个类

性能优化:通过静态匹配减少代理创建的数量

运行时灵活性:通过动态匹配提供基于参数的运行时决策

  1. 验证方法
    您可以通过以下方式验证:
@SpringBootTestclassVerifyTest{@TestvoidverifyProxyCreation(){DataServicedataService=context.getBean(DataService.class);// 验证代理类型System.out.println("Bean类型: "+dataService.getClass().getName());// 输出可能: com.sun.proxy.$ProxyXX 或 DataService$$EnhancerBySpringCGLIB$$// 验证方法是否被代理System.out.println("findById 方法是否被代理: "+AopUtils.isAopProxy(dataService)&&AopUtils.isCglibProxy(dataService));// 查看代理的拦截器if(AopUtils.isAopProxy(dataService)){Advisedadvised=(Advised)dataService;System.out.println("拦截器数量: "+advised.getAdvisors().length);for(Advisoradvisor:advised.getAdvisors()){System.out.println("拦截器: "+advisor.getClass().getName());}}}}

总结回答您的问题
Q: 在容器初始化节点会根据静态Pointcut创建被代理的代理对象,那动态Pointcut?

A: 动态切入点(DynamicMethodMatcherPointcut)在容器初始化时:

同样会根据静态匹配结果创建代理:Spring调用matches(Method, Class<?>),为返回true的方法创建代理

代理内部包含动态检查逻辑:创建的代理对象会包含额外的代码来处理动态匹配

运行时执行动态决策:每次方法调用时,代理会执行matches(Method, Class<?>, Object...)来决定是否触发通知

不是两个独立的代理:不存在"静态代理"和"动态代理"两个对象,而是一个代理对象包含了动态匹配的能力

简单来说:动态切入点也是基于静态匹配创建代理的,但代理内部多了运行时参数检查的逻辑

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

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

相关文章

gb/t4857.23-2021

新版本为GB/T 4857.23-2021《包装 运输包装件基本试验 第23部分&#xff1a;垂直随机振动试验方法》&#xff0c;更新的技术亮点主要是将原来的随机振动更改为垂直随机振动&#xff0c;用于模拟车辆行驶过程中垂直方向的非周期性振动&#xff0c;更贴近真实的运输场景&#xff…

揭秘免费AI写论文秘密:8款神器半天5000字全学科覆盖

开头&#xff1a;90%学生不知道的“论文黑科技”&#xff0c;导师私藏的效率密码 你是否经历过&#xff1a;深夜对着空白文档发呆&#xff0c;导师的“修改意见”像天书一样难懂&#xff0c;查重率居高不下却无从下手&#xff1f;90%的科研党都在靠“蛮力”写论文——但其实&a…

告别“定制难、迭代慢”:低代码重构数字化OA的技术逻辑与实践路径

在企业数字化转型的攻坚阶段&#xff0c;OA系统早已不是“电子审批文档传阅”的简单工具&#xff0c;而是承载组织协同效率、业务流程贯通、数据资产沉淀的核心中枢。但长期以来&#xff0c;传统OA开发模式始终陷入“定制开发周期长、需求变更响应慢、跨系统集成难”的三重困境…

如何破局ERP与MES系统集成之“锁”?从“数据孤岛”到“生产大脑”的深度集成之路

“不打破ERP与MES间的数据壁障&#xff0c;智能制造就是一场昂贵的数字模拟。” 对于中国数百万向数字化、智能化转型的制造企业而言&#xff0c;生产运营效率的真正跃升&#xff0c;始于ERP&#xff08;企业资源计划&#xff09;与MES&#xff08;制造执行系统&#xff09;的无…

实测对比:CSANMT与百度翻译API在专业术语上的表现差异

实测对比&#xff1a;CSANMT与百度翻译API在专业术语上的表现差异 &#x1f4d6; 背景与问题提出 随着全球化进程加速&#xff0c;高质量的中英翻译服务在科研、工程、医疗、法律等专业领域的需求日益增长。尽管通用翻译引擎&#xff08;如百度翻译、Google Translate&#x…

中小团队如何高效构建“价值型IP”?知识付费的下一个机会点

当流量红利逐渐平缓&#xff0c;大规模、粗放式的矩阵运营模式面临成本与效率的双重挑战。知识付费领域正在显露出一个清晰的趋势&#xff1a;基于中小型精锐团队的、深度价值驱动的IP模式&#xff0c;正成为更具韧性、更可持续的发展路径。 这并非退而求其次&#xff0c;而是在…

导师严选9个AI论文网站,助你轻松搞定本科生毕业论文!

导师严选9个AI论文网站&#xff0c;助你轻松搞定本科生毕业论文&#xff01; AI 工具助你轻松应对论文写作难题 在当今信息化时代&#xff0c;AI 工具已经渗透到各个领域&#xff0c;学术写作也不例外。对于本科生而言&#xff0c;毕业论文的撰写是一项既重要又复杂的任务&…

区县政府官员变动DID数据(2010-2024)

数据简介CNPaperData本数据以胡佳胤等&#xff08;2024&#xff09;《政策导向、官员变更与企业破产——来自裁判文书的证据》&#xff0c;构建区县政府官员变动DID虚拟变量。地区官员变动作为一种制度性安排&#xff0c;对经济发展产生着深远且复杂的影响&#xff0c;其意义绝…

基于java+ vue中老年人文化活动平台系统(源码+数据库+文档)

中老年人文化活动平台系统 目录 基于springboot vue中老年人文化活动平台系统 一、前言 二、系统功能演示 三、技术选型 四、其他项目参考 五、代码参考 六、测试参考 七、最新计算机毕设选题推荐 八、源码获取&#xff1a; 基于springboot vue中老年人文化活动平台…

零基础学会Leaflet:你的第一个地图应用

快速体验 打开 InsCode(快马)平台 https://www.inscode.net输入框内输入如下内容&#xff1a; 创建一个适合新手的Leaflet教学项目&#xff0c;实现一个简单的城市景点地图。要求&#xff1a;1) 分步骤注释代码 2) 包含5个预设标记点 3) 点击标记显示简单信息 4) 添加一个基础…

零基础部署M2FP模型:CPU环境下的稳定运行指南

零基础部署M2FP模型&#xff1a;CPU环境下的稳定运行指南 &#x1f4d6; 项目简介&#xff1a;什么是M2FP多人人体解析服务&#xff1f; 在计算机视觉领域&#xff0c;人体解析&#xff08;Human Parsing&#xff09; 是一项比普通语义分割更精细的任务——它不仅识别“人”这…

Python如何使用DrissionPage做自动化:简单入门指南

在Python自动化领域&#xff0c;Selenium和Requests是两个常用工具&#xff0c;但各有局限。DrissionPage巧妙结合了两者优势&#xff0c;既能用浏览器自动化处理动态页面&#xff0c;又能通过HTTP请求提升效率。本文将带你从零开始&#xff0c;用10分钟掌握DrissionPage的核心…

从“流量为王”到“价值共生”:知识付费IP如何穿越周期?

过去的几年&#xff0c;知识内容领域经历了堪称“狂飙”的时代。短视频的崛起、矩阵的铺开、海量线索的涌入&#xff0c;让许多人相信&#xff0c;增长的核心在于流量的获取与转化能力。然而&#xff0c;当平台规则迭代、算法逻辑变迁&#xff0c;不少曾依赖单一渠道或方法论的…

31.useHover

React useHover 钩子:如何优雅地处理元素悬停状态? 在 Web 应用开发中,处理元素的悬停状态是一个常见需求,用于实现交互式界面元素、工具提示等功能。useHover 钩子提供了一种简洁而有效的方式来在 React 组件中监听和响应元素的悬停状态。这个自定义钩子不仅简化了悬停状…

AI智能体检平台:把“精准健康管家”搬进体检中心

提起体检&#xff0c;不少人都有困扰&#xff1a;排队久、等报告要一周&#xff0c;拿到报告全是专业术语看不懂&#xff0c;更怕医生漏查早期小问题。AI智能体检平台刚好解决这些痛点&#xff0c;它不是简单给体检设备加个“智能外套”&#xff0c;而是靠AI算法打通体检全流程…

M2FP模型压缩:剪枝与量化联合优化

M2FP模型压缩&#xff1a;剪枝与量化联合优化 &#x1f4cc; 引言&#xff1a;从高性能到高效能的跨越 在实际工业部署中&#xff0c;高精度模型往往面临推理延迟高、资源消耗大等挑战。M2FP&#xff08;Mask2Former-Parsing&#xff09; 作为当前多人人体解析任务中的SOTA模型…

基于java+ vue高校就业管理系统(源码+数据库+文档)

高校就业管理 目录 基于ssm vue高校就业管理系统 一、前言 二、系统功能演示 三、技术选型 四、其他项目参考 五、代码参考 六、测试参考 七、最新计算机毕设选题推荐 八、源码获取&#xff1a; 基于ssm vue高校就业管理系统 一、前言 博主介绍&#xff1a;✌️大厂码…

vue3+Thinkphp的旅拍在线婚纱摄影网站的设计与实现

目录摘要项目开发技术介绍PHP核心代码部分展示系统结论源码获取/同行可拿货,招校园代理摘要 随着互联网技术的发展&#xff0c;旅拍和在线婚纱摄影服务需求日益增长&#xff0c;传统线下服务模式已无法满足用户便捷化、个性化的需求。基于Vue3前端框架和ThinkPHP后端框架&…

上海AI实验室突破:AI实现高效思考模式告别冗余计算

这项由上海AI实验室的刘俊楠、刘宏伟、张松阳和陈恺团队完成的研究发表于2025年12月&#xff0c;论文编号为arXiv:2512.01925v1。研究团队还包括来自莫纳什大学的成员&#xff0c;感兴趣的读者可以通过该编号查询完整论文。当我们遇到数学难题时&#xff0c;有些同学能够直接抓…

模型推理慢?CSANMT针对CPU指令集深度优化提速

模型推理慢&#xff1f;CSANMT针对CPU指令集深度优化提速 &#x1f310; AI 智能中英翻译服务&#xff08;WebUI API&#xff09; 在当前全球化背景下&#xff0c;高质量的机器翻译已成为跨语言沟通的核心基础设施。尤其在中小企业、开发者工具链和轻量级应用中&#xff0c;…