当前位置: 首页 > article >正文

AspectJ编译期织入实战

JDK动态代理对final类/方法增强无效CGLIB因继承机制无法代理final类/方法。当业务场景中必须使用final类如工具类、第三方依赖类或final方法时Spring AOP动态代理已无法满足需求此时需使用AspectJ编译期织入实现AOP增强。本文核心用规范的开发示例讲解AspectJ编译期织入的配置、编码、编译运行全流程解决final类/方法的AOP增强痛点贴合实际开发规范。一、核心前提AspectJ编译期织入原理与Spring AOP运行时动态代理不同AspectJ编译期织入是在代码编译阶段将切面逻辑通知直接织入目标类的字节码中生成包含增强逻辑的class文件。核心优势不依赖动态代理不受final类/方法的限制——无论目标类/方法是否为final只要匹配切点规则就能实现增强且性能优于运行时代理无反射开销。关键区别Spring AOP是“运行时增强”AspectJ编译期织入是“编译时增强”直接修改目标类字节码无需代理对象。二、规范开发示例SpringBoot AspectJ 编译期织入以“final工具类的方法增强日志记录”为实战场景完整演示从依赖配置、切面编写、编译配置到测试运行的全流程符合企业开发规范。2.1 场景定义假设存在一个final工具类业务要求必须为final防止被继承篡改需对其内部的final方法添加日志增强记录方法调用参数、返回值和执行耗时。/** * 业务要求必须为final类工具类禁止继承 * 内部方法为final禁止重写 */publicfinalclassFinalToolUtil{/** * final方法业务核心工具方法需添加日志增强 * param param 入参 * return 处理结果 */publicfinalStringprocess(Stringparam){// 模拟业务逻辑参数处理try{Thread.sleep(100);// 模拟处理耗时}catch(InterruptedExceptione){thrownewRuntimeException(处理失败,e);}return处理结果param.toUpperCase();}}2.2 第一步添加依赖SpringBoot项目需添加AspectJ核心依赖和编译期织入插件确保编译时能将切面逻辑织入目标类。pom.xml 配置规范依赖版本贴合SpringBoot版本!-- SpringBoot 基础依赖省略根据自身版本引入 --!-- 1. AspectJ 核心依赖 --dependencygroupIdorg.aspectj/groupIdartifactIdaspectjrt/artifactIdversion1.9.19/version/dependency!-- 2. AspectJ 编译期织入插件关键 --buildpluginsplugingroupIdorg.codehaus.mojo/groupIdartifactIdaspectj-maven-plugin/artifactIdversion1.14.0/versionconfiguration!-- 指定Java版本与项目一致 --source1.8/sourcetarget1.8/targetcomplianceLevel1.8/complianceLevel!-- 指定切面类所在包扫描切面 --aspectLibrariesaspectLibrarygroupIdorg.aspectj/groupIdartifactIdaspectjrt/artifactId/aspectLibrary/aspectLibraries/configurationexecutionsexecutiongoals!-- 编译时织入 --goalcompile/goalgoaltest-compile/goal/goals/execution/executions/plugin/plugins/build说明aspectj-maven-plugin 是编译期织入的核心负责在maven编译阶段将切面逻辑织入目标类字节码。2.3 第二步编写AspectJ切面规范编写使用AspectJ注解编写切面定义切点匹配final类的final方法和通知日志增强逻辑遵循AOP开发规范。importorg.aspectj.lang.ProceedingJoinPoint;importorg.aspectj.lang.annotation.Around;importorg.aspectj.lang.annotation.Aspect;importorg.aspectj.lang.annotation.Pointcut;importorg.slf4j.Logger;importorg.slf4j.LoggerFactory;importorg.springframework.stereotype.Component;/** * AspectJ 切面类编译期织入 * 用于增强 FinalToolUtil 的 final 方法 */Aspect// 标识为AspectJ切面Component// 交给Spring管理可选若不依赖Spring可省略publicclassFinalMethodAspect{privatestaticfinalLoggerlogLoggerFactory.getLogger(FinalMethodAspect.class);/** * 切点匹配 FinalToolUtil 类的所有final方法 * 切点表达式规范execution(修饰符 返回值 全类名.方法名(参数)) */Pointcut(execution(public final String com.example.demo.util.FinalToolUtil.process(..)))publicvoidfinalMethodPointcut(){}/** * 环绕通知记录方法调用日志、执行耗时 * 环绕通知可控制方法执行适合记录耗时、异常处理 */Around(finalMethodPointcut())publicObjectaroundFinalMethod(ProceedingJoinPointjoinPoint)throwsThrowable{// 1. 前置增强记录方法调用信息StringmethodNamejoinPoint.getSignature().getName();Object[]argsjoinPoint.getArgs();log.info(【Final方法增强】开始调用方法{}入参{},methodName,args[0]);// 2. 记录开始时间执行目标方法final方法longstartTimeSystem.currentTimeMillis();ObjectresultjoinPoint.proceed();// 执行目标final方法// 3. 后置增强记录执行耗时和返回值longcostTimeSystem.currentTimeMillis()-startTime;log.info(【Final方法增强】方法{}执行完毕耗时{}ms返回值{},methodName,costTime,result);// 4. 返回目标方法结果returnresult;}}关键说明切点表达式必须精准匹配final方法execution(public final String com.example.demo.util.FinalToolUtil.process(..))明确方法的修饰符final、返回值、全类名、方法名和参数。Around通知AspectJ的环绕通知与Spring AOP用法一致可完整控制目标方法的执行流程适合日志、耗时统计等场景。切面类可交给Spring管理Component也可独立使用不依赖Spring本文演示SpringBoot集成场景。2.4 第三步编译验证核心步骤AspectJ编译期织入的核心是“编译阶段织入”需通过maven编译确保切面逻辑被织入FinalToolUtil的字节码中。执行maven编译命令mvn clean compile编译成功后可通过反编译工具如JD-GUI查看FinalToolUtil.class文件会发现切面的日志逻辑已被直接织入process()方法中而非通过代理实现。反编译核心片段示意publicfinalclassFinalToolUtil{publicfinalStringprocess(Stringparam){// 织入的切面逻辑前置日志LoggerlogLoggerFactory.getLogger(FinalMethodAspect.class);StringmethodNameprocess;Object[]argsnewObject[]{param};log.info(【Final方法增强】开始调用方法{}入参{},methodName,args[0]);longstartTimeSystem.currentTimeMillis();// 原业务逻辑try{Thread.sleep(100);}catch(InterruptedExceptione){thrownewRuntimeException(处理失败,e);}Stringresult处理结果param.toUpperCase();// 织入的切面逻辑后置日志longcostTimeSystem.currentTimeMillis()-startTime;log.info(【Final方法增强】方法{}执行完毕耗时{}ms返回值{},methodName,costTime,result);returnresult;}}可见编译后切面逻辑已与目标final方法的业务逻辑融合无需代理直接执行。2.5 第四步测试运行实战验证编写测试类调用FinalToolUtil的process()方法验证AOP增强是否生效日志是否打印。importcom.example.demo.util.FinalToolUtil;importorg.junit.jupiter.api.Test;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.boot.test.context.SpringBootTest;SpringBootTestpublicclassFinalToolUtilTest{// 直接注入final类实例无需代理编译后已包含增强逻辑AutowiredprivateFinalToolUtilfinalToolUtil;TestpublicvoidtestProcess(){// 调用final方法StringresultfinalToolUtil.process(aspectj-test);System.out.println(测试结果result);}}2.6 运行结果符合预期【Final方法增强】开始调用方法process入参aspectj-test 【Final方法增强】方法process执行完毕耗时102ms返回值处理结果ASPECTJ-TEST 测试结果处理结果ASPECTJ-TEST结论final类的final方法成功被增强日志正常打印证明AspectJ编译期织入生效。三、关键注意事项规范开发必看依赖版本一致aspectjrt、aspectj-maven-plugin的版本需匹配避免编译报错本文使用稳定版本组合可直接复用。切点表达式精准必须明确匹配final方法的修饰符final否则无法织入AspectJ支持精准匹配修饰符。编译方式必须使用maven编译mvn compileIDE直接编译可能无法触发AspectJ织入需配置IDE的AspectJ插件如IntelliJ IDEA的AspectJ Support。与Spring AOP区分AspectJ编译期织入无需依赖Spring AOP可独立使用若集成SpringBoot只需添加Component将切面交给Spring管理即可。第三方final类增强若目标final类是第三方依赖无法修改源码只需在切面中精准配置切点表达式编译时同样能织入增强逻辑核心优势。四、总结开发实战结论当遇到final类/方法需要AOP增强时Spring AOPJDK/CGLIB无法解决此时AspectJ编译期织入是最优方案优势不受final限制性能优于动态代理无反射开销支持第三方final类增强。实战流程添加依赖 → 编写切面 → maven编译 → 测试运行符合企业开发规范。适用场景工具类、第三方依赖类、业务要求必须为final的类/方法的AOP增强日志、权限、耗时统计等。本文示例可直接复制到项目中复用只需修改包名、类名和切点表达式即可快速实现final类/方法的AOP增强。

相关文章:

AspectJ编译期织入实战

JDK动态代理对final类/方法增强无效,CGLIB因继承机制无法代理final类/方法。当业务场景中必须使用final类(如工具类、第三方依赖类)或final方法时,Spring AOP(动态代理)已无法满足需求,此时需使…...

线性判别分析LDA

一、降维的基础背景降维的概念与必要性:在机器学习中,降维是指在限定条件下减少随机变量的个数,以提取出不相关的主变量 。由于实际数据常面临多重共线性(导致模型泛化能力弱、高维空间稀疏难以找到特征等问题)&#x…...

每日一Go-55、分布式 ID 生成(雪花算法 / Segment / Redis / DB)

一、为什么分布式系统一定要“自己造ID”? 单机时代,利用数据库的自增ID AUTO_INCREMENT但是在微服务/多实例/分库分表的情况下,会出现:ID冲突数据迁移困难顺序失控跨库无法唯一定位二、分布式ID的核心指标 一个靠谱的ID方案&…...

别再手动对齐了!用Creo的骨架模型做装配,效率提升不止一点点

别再手动对齐了!用Creo的骨架模型重构你的装配设计流程 当你在设计一个包含二十个运动部件的机械臂时,突然接到客户修改行程参数的需求——传统装配方式下,这意味着要逐个调整每个零件的安装位置、重新计算配合间隙、反复检查干涉区域。这种&…...

从HMM到BiLSTM-CRF:我的NER模型进化之路与性能对比实验报告

从HMM到BiLSTM-CRF:我的NER模型进化之路与性能对比实验报告 三年前第一次接触命名实体识别(NER)任务时,我完全没想到这个看似简单的序列标注问题会让我在模型迭代的路上走这么远。从最初用HMM处理简单场景,到引入CRF解决标签依赖问题&#xf…...

从Simulink仿真到STM32烧录:手把手搭建SVPWM算法验证闭环(附模型和工程)

SVPWM算法在电机控制中的全流程实现:从Simulink仿真到STM32硬件验证 电机控制算法的开发往往需要在理论验证和硬件实现之间反复迭代。SVPWM(空间矢量脉宽调制)作为现代电机控制的核心技术,其实现过程涉及数学建模、仿真验证、代码…...

数百种蛋白同步解析:抗体芯片如何重塑WB技术边界

摘要:高通量Western Blot技术通过将传统蛋白质印迹实验与微阵列芯片平台相结合,实现了单次实验中对数百种蛋白质表达水平的同步检测。该技术以抗体芯片为核心载体,显著提升了实验通量与数据可重复性,在蛋白质组学研究中展现出重要…...

86253

825747...

从‘Invalid HTTP status’到稳定连接:UniApp微信小程序WebSocket实战配置详解

从‘Invalid HTTP status’到稳定连接:UniApp微信小程序WebSocket实战配置详解 微信小程序开发中,WebSocket作为实时通信的核心技术,其配置问题常让开发者陷入调试泥潭。最近一位使用UniAppVue3的开发者反馈,真机调试时遭遇Invali…...

LabVIEW 强度图与强度图表

​LabVIEW 中强度图(Intensity Graph)与强度图表(Intensity Chart)均可接收二维数组作为输入,用于二维数据色彩可视化,二者核心差异体现在前面板运行行为上。强度图单次刷新、仅显示当前一组数据&#xff0…...

STC8单片机驱动ESP-01S联网实战:从AT指令到GET请求获取苏宁时间(附完整源码)

STC8单片机与ESP-01S物联网开发实战:从AT指令到云端数据获取 在嵌入式物联网开发中,如何让传统单片机快速接入互联网一直是个热门话题。STC8作为国内广泛使用的51内核单片机,与ESP-01S WiFi模块的组合,为开发者提供了一种经济高效…...

2025最权威的十大AI科研方案解析与推荐

Ai论文网站排名(开题报告、文献综述、降aigc率、降重综合对比) TOP1. 千笔AI TOP2. aipasspaper TOP3. 清北论文 TOP4. 豆包 TOP5. kimi TOP6. deepseek 在人工智能生成内容也就是AIGC越来越普及的背景状况下,把内容里的AI痕迹给降低成…...

2025届学术党必备的六大AI写作工具推荐榜单

Ai论文网站排名(开题报告、文献综述、降aigc率、降重综合对比) TOP1. 千笔AI TOP2. aipasspaper TOP3. 清北论文 TOP4. 豆包 TOP5. kimi TOP6. deepseek 于内容创作里头,要去减退AIGC(人工智能生成内容)的那种被…...

词袋模型(Bag Of Words)在文本分类中的原理与实践

1. 文本分类与预测的Bag Of Words方法解析在自然语言处理领域,文本分类是最基础也最实用的任务之一。我十年前第一次接触这个课题时,Bag Of Words(词袋模型)就像一把瑞士军刀,简单却异常有效。直到今天,虽然…...

AI与IoT融合:智能边缘计算的应用与挑战

1. AI与IoT融合:产业变革的核心驱动力在医疗机构的术后恢复病房里,护士们正疲于奔命地监测数十位患者的康复活动量。传统的人工监测方式既无法保证及时性,又难以做到精确量化——这正是微软首席技术官Kevin Scott在妻子术后康复期间观察到的真…...

手把手教你用LabVIEW驱动Zebra GX420d串口打印机(附完整源码与模板文件)

手把手教你用LabVIEW驱动Zebra GX420d串口打印机(附完整源码与模板文件) 在工业自动化领域,标签打印是产线管理、设备标识和物流追踪的关键环节。Zebra GX420d作为一款经典的工业级热敏打印机,以其稳定的串口通信和可靠的打印质量…...

STM32定时器实战:PWMI双通道捕获解析PWM信号(频率与占空比测量)

1. PWM信号测量基础与STM32定时器概述 PWM(脉冲宽度调制)信号是嵌入式系统中常见的控制信号,广泛应用于电机调速、LED调光、电源管理等领域。一个完整的PWM信号包含两个关键参数:频率和占空比。频率决定了信号周期的快慢&#xff…...

Linux内核开发工具之Sparse

https://notes.z-dd.online/2026/01/22/Linux%E5%86%85%E6%A0%B8%E5%BC%80%E5%8F%91%E5%B7%A5%E5%85%B7%E4%B9%8BSparse/https://notes.z-dd.online/2026/01/22/Linux%E5%86%85%E6%A0%B8%E5%BC%80%E5%8F%91%E5%B7%A5%E5%85%B7%E4%B9%8BSparse/ Linux内核开发工具之Sparse 概述…...

用像素语言·跨维传送门,5步搭建你的专属多语言翻译像素工坊

用像素语言跨维传送门,5步搭建你的专属多语言翻译像素工坊 1. 像素冒险工坊初探 1.1 打破次元壁的翻译体验 像素语言跨维传送门(Pixel Language Portal)彻底颠覆了传统翻译工具的刻板印象。这款基于腾讯混元MT-7B引擎的翻译终端&#xff0…...

STM32寄存器驱动LED流水灯:从仿真到实物的全流程实践

1. 从零开始理解STM32寄存器编程 第一次接触STM32寄存器编程时,我完全被那些十六进制地址和位操作搞懵了。但后来发现,寄存器编程就像直接跟硬件对话,比库函数更接近芯片本质。想象一下,你面前有8个灯泡(LED&#xff0…...

拆解材料成本率控制系统的三大功能,看如何控制材料成本率解决原材料浪费难题

在制造企业的成本构成中,原材料通常占据50%到70%的比重。这意味着,管好了材料成本,就等于抓住了利润的牛鼻子。但很多工厂的现实是:订单报价时毛利可观,月底一算账,利润被吃掉一大截——材料浪费严重、超支…...

拆解工厂物料管理系统,看工厂物料管理系统如何解决账实不符

在工厂的日常运营中,物料管理是最基础也最容易出问题的环节。你可能会遇到这样的情况:仓库账面上显示还有100个零件,生产急用时却翻遍货架找不到;采购按计划下单,结果库存早已积压;月底盘点,账实…...

治愈不内卷!星露谷物语v1.6.15,承包你的所有温柔时光

如果你被快节奏的生活压得喘不过气,被内耗裹挟得身心俱疲,那一定要试试《星露谷物语》v1.6.15版本——这款Steam好评率98%的治愈神作,用一方小小农场,给你一个逃离喧嚣的精神避风港。 今天,就有免费的pc资源&#xff1…...

用Multisim复现2012年电赛A题:手把手教你搭建AD630锁定放大器(含完整仿真文件)

用Multisim复现2012年电赛A题:手把手教你搭建AD630锁定放大器(含完整仿真文件) 锁定放大器作为微弱信号检测的核心器件,在科研测量、工业检测等领域具有不可替代的作用。2012年全国大学生电子设计竞赛A题要求参赛者在强噪声背景下…...

计算机毕业设计:Python大盘行情与个股诊断预测系统 Flask框架 TensorFlow LSTM 数据分析 可视化 大数据 大模型(建议收藏)✅

博主介绍:✌全网粉丝10W,前互联网大厂软件研发、集结硕博英豪成立工作室。专注于计算机相关专业项目实战6年之久,选择我们就是选择放心、选择安心毕业✌ > 🍅想要获取完整文章或者源码,或者代做,拉到文章底部即可与…...

MySQL触发器在主从架构下的表现_MySQL触发器主从同步策略

触发器在从库默认不执行,主从复制仅同步binlog事件而非触发器逻辑,从库需手动创建且受read_only和DEFINER权限限制;可靠替代方案是应用层双写、binlog监听或定时对账。触发器在从库上默认不执行MySQL主从复制只同步 binlog 事件,不…...

基于stm32设计智能消防小车(有完整资料)

资料查找方式:特纳斯电子(电子校园网):搜索下面编号即可编号:T1602310M设计简介:本设计是基于stm32设计智能消防小车,主要实现以下功能:通过超声波测距模块进行测距 通过火焰传感器进…...

测试库与生产库怎么仅同步新增增量数据_无损发布与更新方案

pg_dump --inserts ON CONFLICT DO NOTHING 可安全实现增量同步:先用 --inserts 导出新增数据,再用 sed 替换为 INSERT ... ON CONFLICT DO NOTHING,依赖唯一约束跳过重复,避免误更新或主键冲突。如何用 pg_dump --inserts --…...

Agenus 指定 BAP Pharma 为 BOT+BAL 准入项目全球独家合作伙伴

• 本次合作将通过法国政府报销的 Autorisation d’Accs Compassionnel(AAC),以及部分国家的付费指定患者用药项目(Named Patient Programs,NPP),为患者及时获取 botensilimab 联合 balstilimab…...

别再死记硬背了!用生活中的例子和动画,5分钟搞懂杨氏双缝干涉到底在说什么

用生活中的波纹和光影游戏,轻松理解杨氏双缝干涉 想象一下,当你同时往平静的池塘里扔进两块小石子,水面上会形成两圈向外扩散的波纹。当这两组波纹相遇时,有些地方的水面起伏特别剧烈,有些地方却异常平静——这就是波动…...