那么当这两件事冲突时,Spring Boot 是怎么“解决”的呢?

答案是:它不解决,也无法解决。当这种情况发生时,你的应用程序会直接启动失败。

这不是 Spring Boot 的疏忽,而是由 CGLIB 的底层原理和 Java 语言的规则所决定的。

工作流程和失败原因

让我们来模拟一下 Spring Boot 启动时会发生什么:

  1. Spring 容器开始创建所有的 Bean。
  1. 它找到了一个需要被 AOP 增强的 Bean(例如,一个被 @Service 注解的类,并且它的方法匹配了某个 @Aspect 切面)。
  1. Spring Boot 查看 AOP 配置,发现默认使用 CGLIB (proxy-target-class=true)。
  1. 它尝试为这个 Bean 创建一个代理。CGLIB 上场,准备动态地创建这个 Bean 的一个子类。
  1. 此时,CGLIB 发现这个 Bean 的类是 final 的。
  1. Java 语法规定 final 类不能被继承。CGLIB 的核心机制被阻断了。
  1. CGLIB 抛出一个异常。
  1. 这个异常会向上传递,最终导致 Spring 容器无法创建这个 Bean。
  1. Bean 创建失败,整个 Spring 应用程序的启动过程被中断,并抛出 BeanCreationException 或类似的错误。

你通常会在控制台日志中看到非常明确的错误信息,它会告诉你:

> Caused by: java.lang.IllegalArgumentException: Cannot subclass final class com.example.YourFinalService

这个错误是响亮而明确的 (Fail-fast)。它在启动时就告诉你“此路不通”,而不是在运行时产生一些难以预料的奇怪行为。

为什么 Spring Boot 仍然选择 CGLIB 作为默认?

这是一个设计上的权衡取舍。Spring Boot 的设计者认为:

  1. final 业务类是少数情况:在大多数业务应用开发中,开发者很少会将自己写的 Service 或 Component 类声明为 final。
  1. 内部调用 AOP 失效问题更常见、更隐蔽:相比之下,使用 JDK 代理时,开发者在同一个类中调用 this.anotherMethod() 导致 AOP 失效的问题,是一个非常常见且容易让人困惑的陷阱。它不会报错,只是静默地不工作,非常难以排查。

所以,Spring Boot 选择了“长痛不如短痛”:

  • 默认 CGLIB:解决了那个常见且隐蔽的“内部调用”问题,让 AOP 的行为在95%的场景下都符合直觉。
  • 代价:当遇到那5%的 final 类场景时,它会以一种非常直接、暴力的方式(启动失败)来提醒开发者。

总结:开发者如何应对?:

  • 首选方案:如果代码可控,移除 final 关键字。这是最简单、最直接的修复方式。
  • 备选方案:如果不能移除 final,就为这个类提取一个接口,然后在注入点使用接口,让 AOP 可以通过 JDK 代理工作(但这可能需要你手动将 spring.aop.proxy-target-class 设置为 false,或者进行更细粒度的控制)。
  • 终极方案:如果以上都不行,才考虑使用 AspectJ 静态织入。

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

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

相关文章

cuda编程笔记(10)--memory access 优化

全局内存访问优化(Coalesced Access) 什么是 Coalesced Access? 定义:一个 warp(32 个线程)在同一指令中访问全局内存时,如果这些访问请求可以合并成尽可能少的内存事务(通常是 32…

闲庭信步使用图像验证平台加速FPGA的开发:第三十一课——车牌识别的FPGA实现(3)车牌字符分割预处理

(本系列只需要modelsim即可完成数字图像的处理,每个工程都搭建了全自动化的仿真环境,只需要双击top_tb.bat文件就可以完成整个的仿真,大大降低了初学者的门槛!!!!如需要该系列的工程…

电子电气架构 --- 汽车软件全生命周期

我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 简单,单纯,喜欢独处,独来独往,不易合同频过着接地气的生活,除了生存温饱问题之外,没有什么过多的欲望,表面看起来很高冷,内心热情,如果你身…

力扣面试150(41/150)

7.25 56. 合并区间 以数组 intervals 表示若干个区间的集合,其中单个区间为 intervals[i] [starti, endi] 。请你合并所有重叠的区间,并返回 一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区间 。 我的思路: 左端点升序…

【隧道篇 / IPsec】(7.6) ❀ 01. 利用向导快速建立IPsec安全隧道 (点对点) ❀ FortiGate 防火墙

【简介】相信很多人已经习惯利用导向快速创建VPN了,而且已经有部分尝鲜者已经用上了FortiOS 7.6,但是会发现FortiOS 7.6下的VPN向导改变了很多,一时无法下手,下面我们来看看最常见的点对点是如何配置的。环境介绍在配置IPsec VPN之…

PLLIP核

。1 号红色框内的速度等级代表着设备的速度 等级,保存默认就好;2 号红色框内设置输入频率;3 号红色框选择 PLL 的工作模式。我们 开发板用的晶振是 50MHz 的,故在 2 号红色框内我们填写 50MHz;我们在 3 号红色框内选正…

1.1 Deep learning?pytorch ?深度学习训练出来的模型通常有效但无法解释合理性? 如何 解释?

DL 是什么,你如何理解DL模型? DL 对于我而言,就是人类试图想通过数学语言描述人类学习过程的一门技术,或者说学科。 因此 DL 模型 相当于 数学 的 一个 funciton ,有输入,通过function处理,得…

java实现在工具类中注入其他对象方式

方案1: Slf4j Component public class ChatdocApiClient {Value("${chatdoc.app-id}")private String appId;Value("${chatdoc.secret}")private String secret;Value("${chatdoc.domain}")private String domain;private final Rest…

electron中IPC 渲染进程与主进程通信方法解析

electron中ipcRenderer.invoke、ipcRenderer.on、ipcRenderer.send、ipcRenderer.sendSync作用与区别 IPC 渲染进程与主进程通信方法解析 ipcRenderer 的这几个方法作用不完全相同,它们适用于不同的通信场景,核心区别在于通信方向、是否需要响应以及同步…

epoll_event 事件类型详解

epoll_event 事件类型详解 epoll_event 是 Linux epoll I/O 多路复用机制的核心结构体&#xff0c;其中的事件类型决定了 epoll 监控的行为和触发条件。以下是各种事件类型的详细解析&#xff1a; epoll_event 结构体 #include <sys/epoll.h>typedef union epoll_data {v…

设计自己的小传输协议 导论与概念

设计自己的小传输协议 导论与概念 1&#xff1a;聊一聊协议头设计 ​ 早在《TCP/IP详解》中的第一句话中&#xff0c;我们就知道协议的含义是这样的&#xff1a;协议是通信双方共同遵守的一套规则&#xff0c;提供格式定义、语义解释等&#xff0c;使不同设备或软件能够正确交…

iOS —— 天气预报仿写总结

在iOS中&#xff0c;最常见的网络请求方式是NSURLSession&#xff0c;它是苹果推荐的现代API&#xff0c;简单安全且易于拓展。一次完整的网络请求流程&#xff1a;构造 NSURL 对象创建 NSURLSessionDataTask发起请求&#xff08;resume&#xff09;在回调中解析数据回到主线程…

MySQL 8.4 Windows 版安装记录与步骤参考

导语&#xff1a; MySQL 作为广泛使用的开源数据库管理系统&#xff0c;是许多开发者和学习者的必备工具。最近有朋友询问安装过程&#xff0c;正好整理了 MySQL 8.4 在 Windows 系统下的安装步骤和一些注意事项&#xff0c;分享给有需要的朋友做个参考。关于 MySQL&#xff1a…

七、搭建springCloudAlibaba2021.1版本分布式微服务-skywalking9.0链路追踪

前言链路追踪介绍 对于一个大型的几十个&#xff0c;几百个微服务构成的微服务架构系统&#xff0c;通常会遇到下面的一系列问题。 如何串联整个调用链路&#xff0c;快速定位问题&#xff1f;如何澄清各个微服务之间的依赖关系&#xff1f;如何进行各个微服务接口的性能分析&a…

深入理解大语言模型生成参数:temperature、top\_k、top\_p 等全解析

在使用大语言模型&#xff08;如 GPT-4、LLaMA、ChatGLM 等&#xff09;进行文本生成任务时&#xff0c;很多开发者会面对各种“生成参数”&#xff0c;如 temperature、top_k、top_p、repetition_penalty 等。这些参数虽然看起来抽象&#xff0c;但掌握它们的意义和配置技巧&a…

vulhub Web Machine(N7)靶场攻略

下载地址&#xff1a; https://download.vulnhub.com/webmachine/Web-Machine-N7.ova 使用方法&#xff1a; 靶场下载好以后不用解压&#xff0c;需要使用Oracle VirtualBox虚拟机打开&#xff0c;用VMware会报错。安装Oracle VirtualBox虚拟机时安装地址不能随便选择&#…

【机器学习深度学习】模型微调:多久才算微调完成?——如何判断微调收敛,何时终止训练

目录 前言 一、微调过程的目标&#xff1a;优化模型表现 二、微调需要多久&#xff1f; 微调时间无法确定 三、如何判断微调何时收敛&#xff1f; 3.1 观察Loss的下降趋势 3.2 损失值趋于平稳&#xff0c;意味着收敛 如何识别收敛&#xff1f; 3.3 验证Loss的波动&…

红队视角:实战渗透测试中漏洞利用的进阶技巧与防御

红队作为渗透测试的 “攻击方”&#xff0c;其核心价值不仅在于发现漏洞&#xff0c;更在于挖掘漏洞的深度利用方式 —— 通过绕过防护措施、组合低危漏洞形成攻击链&#xff0c;暴露企业真实安全风险。从红队视角解析漏洞利用的进阶技巧&#xff0c;既能帮助防御方理解攻击思路…

OpenHarmony BUILD.gn中执行脚本

在OpenHarmony编译构建中笔者经常遇到这样的场景——需要执行sh脚本完成某些操作。笔者将OpenHarmony BUILD.gn中执行脚本的方法分享如下&#xff1a; 前置知识点 1.能够把自定义的子系统加入OpenHarmony源码的编译构建&#xff0c;请参考&#xff1a;https://ost.51cto.com/…

QUIC协议如何在UDP基础上解决网络切换问题

一、UDP 四元组的本质局限UDP 本身无连接状态&#xff0c;其数据包仅通过四元组寻址。但 QUIC 在 UDP 之上构建了完整的连接语义。二、QUIC 的连接迁移核心机制1. 连接标识符&#xff08;Connection ID&#xff09;关键设计&#xff1a;每个 QUIC 连接拥有全局唯一 64-bit Conn…