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

Spring - 循环依赖

一、循环依赖概览1.1 什么是循环依赖循环依赖是指两个或多个 Bean 之间互相持有对方引用形成闭环。例如 A 依赖 BB 又依赖 A。A 依赖 BB 依赖 A1.2 循环依赖的三种类型// 类型1构造器注入的循环依赖无法解决 Component public class ServiceA { private final ServiceB serviceB; Autowired public ServiceA(ServiceB serviceB) { this.serviceB serviceB; } } // 类型2Setter/字段注入的循环依赖可以解决 Component public class ServiceA { Autowired private ServiceB serviceB; } // 类型3多 Bean 间接循环 A - B - C - A1.3 Spring 能解决哪些循环依赖注入方式单例 Bean原型 BeanSetter / 字段注入✅ 可以解决❌ 无法解决构造器注入❌ 无法解决❌ 无法解决核心结论Spring 只能解决单例 Setter/字段注入的循环依赖其他情况都会报BeanCurrentlyInCreationException。二、三级缓存原理2.1 三级缓存是什么三级缓存定义在DefaultSingletonBeanRegistry中本质是三个 Map// org.springframework.beans.factory.support.DefaultSingletonBeanRegistry /** 一级缓存完整的单例 BeankeybeanName, value完全初始化后的 Bean */ private final MapString, Object singletonObjects new ConcurrentHashMap(256); /** 二级缓存早期暴露的 Bean已实例化但未完全初始化 */ private final MapString, Object earlySingletonObjects new ConcurrentHashMap(16); /** 三级缓存Bean 工厂用于生成早期引用可能包含 AOP 代理 */ private final MapString, ObjectFactory? singletonFactories new HashMap(16);2.2 三个缓存各自的作用缓存名称存放内容作用一级缓存singletonObjects完整的 Bean实例化 属性注入 初始化完成日常 getBean 获取的就是它二级缓存earlySingletonObjects早期的 Bean已实例化属性可能未填充完保存从三级缓存创建的早期引用避免重复创建代理三级缓存singletonFactoriesObjectFactoryBean 工厂 lambda延迟生成早期引用需要时才调用 getObject()保证 AOP 代理只创建一次2.3 三个缓存的生命周期Bean 开始创建实例化完成调用构造器存入三级缓存singletonFactories其他 Bean 引用本 Bean从三级缓存获取调用 ObjectFactory.getObject存入二级缓存earlySingletonObjects从三级缓存移除本 Bean 属性填充 初始化完成存入一级缓存singletonObjects从二级缓存移除核心要点三级缓存的 ObjectFactory 是在实例化之后、属性填充之前存入的。这意味着此时的 Bean 只是一个空壳调用了构造器但依赖还没注入但它的引用已经可以被其他 Bean 拿到了。三、Setter 注入解决全流程3.1 经典场景A → B → AComponent public class A { Autowired private B b; } Component public class B { Autowired private A a; }3.2 完整流程图ClientSpring 容器一级缓存二级缓存三级缓存getBean(a)检查一级缓存null标记 A 正在创建实例化 Anew A将 A 的 ObjectFactory 存入三级缓存属性填充发现需要 BgetBean(b)检查一级缓存null标记 B 正在创建实例化 Bnew B将 B 的 ObjectFactory 存入三级缓存属性填充发现需要 AgetBean(a) 第二次检查一级缓存null检查 A 是否正在创建是检查二级缓存null检查三级缓存找到 A 的 ObjectFactory调用 getObject() 获取 A 的早期引用将 A 的早期引用存入二级缓存从三级缓存移除 A返回 A 的早期引用给 BB 属性填充完成B 初始化完成将 B 存入一级缓存从二级缓存移除 BB 创建完成注入到 AA 属性填充完成A 初始化完成将 A 存入一级缓存从二级缓存移除 A返回 AClientSpring 容器一级缓存二级缓存三级缓存3.3 关键源码getSingleton() — 三级缓存查找// org.springframework.beans.factory.support.DefaultSingletonBeanRegistry protected Object getSingleton(String beanName, boolean allowEarlyReference) { // 1. 从一级缓存获取完整 Bean Object singletonObject this.singletonObjects.get(beanName); // 2. 一级缓存没有 且 当前 Bean 正在创建中 if (singletonObject null isSingletonCurrentlyInCreation(beanName)) { // 3. 从二级缓存获取早期 Bean singletonObject this.earlySingletonObjects.get(beanName); // 4. 二级缓存也没有 且 允许早期引用 if (singletonObject null allowEarlyReference) { synchronized (this.singletonObjects) { // 5. 双重检查锁 singletonObject this.singletonObjects.get(beanName); if (singletonObject null) { singletonObject this.earlySingletonObjects.get(beanName); if (singletonObject null) { // 6. 从三级缓存获取工厂 ObjectFactory? singletonFactory this.singletonFactories.get(beanName); if (singletonFactory ! null) { // 7. 调用工厂创建早期引用核心 singletonObject singletonFactory.getObject(); // 8. 升级到二级缓存 this.earlySingletonObjects.put(beanName, singletonObject); // 9. 从三级缓存移除 this.singletonFactories.remove(beanName); } } } } } } return singletonObject; }注意三级缓存中的ObjectFactory.getObject()调用的是getEarlyBeanReference()如果该 Bean 需要 AOP 代理这里就会提前创建代理对象。3.4 关键源码doCreateBean() — 暴露到三级缓存// org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory protected Object doCreateBean(String beanName, RootBeanDefinition mbd, Object[] args) { // 1. 实例化 Bean调用构造器 BeanWrapper instanceWrapper createBeanInstance(beanName, mbd, args); Object bean instanceWrapper.getWrappedInstance(); // 2. 提前暴露 Bean 的早期引用 — 解决循环依赖的关键 boolean earlySingletonExposure (mbd.isSingleton() this.allowCircularReferences isSingletonCurrentlyInCreation(beanName)); if (earlySingletonExposure) { addSingletonFactory(beanName, () - getEarlyBeanReference(beanName, mbd, bean)); } // 3. 属性填充依赖注入在这里发生 Object exposedObject bean; populateBean(beanName, mbd, instanceWrapper); // 4. 初始化 Bean exposedObject initializeBean(beanName, exposedObject, mbd); return exposedObject; }3.5 关键源码addSingletonFactory()// org.springframework.beans.factory.support.DefaultSingletonBeanRegistry protected void addSingletonFactory(String beanName, ObjectFactory? singletonFactory) { synchronized (this.singletonObjects) { if (!this.singletonObjects.containsKey(beanName)) { // 存入三级缓存 this.singletonFactories.put(beanName, singletonFactory); // 从二级缓存移除保证只在一个缓存中 this.earlySingletonObjects.remove(beanName); this.registeredSingletons.add(beanName); } } }3.6 完整流程简述面试话术Spring 创建 A先实例化 A调用构造器将 A 的 ObjectFactory 存入三级缓存A 属性填充时发现需要 B去创建 BB 实例化后存入三级缓存属性填充时发现需要 AB 调用 getBean(a)先查一级缓存没有再查二级缓存没有从三级缓存中找到 A 的 ObjectFactory调用 getObject() 获取 A 的早期引用将 A 的早期引用从三级缓存升级到二级缓存移除三级缓存中的 AB 拿到 A 的早期引用完成属性填充和初始化存入一级缓存回到 A拿到完整的 B完成属性填充和初始化存入一级缓存四、为什么是三级而非二级4.1 核心原因支持 AOP 代理延迟创建如果只有二级缓存在实例化后直接创建代理对象存入二级缓存。但问题是如果没有循环依赖AOP 代理应该在初始化后创建BeanPostProcessor#postProcessAfterInitialization而不是提前创建。三级缓存的作用ObjectFactory 是一个工厂lambda只有在真正发生循环依赖时才调用 getObject()。如果不存在循环依赖这个工厂永远不会被调用代理对象会在正常的初始化后阶段创建。4.2 对比分析flowchart TD subgraph 二级缓存方案 A2[实例化 A] -- B2[立即创建代理对象] B2 -- C2[代理对象存入二级缓存] C2 -- D2{是否发生循环依赖?} D2 --|是| E2[正常代理被使用] D2 --|否| F2[代理被创建但从未使用br/浪费性能 代理对象不对] end subgraph 三级缓存方案[三级缓存方案] A3[实例化 A] -- B3[ObjectFactory 存入三级缓存] B3 -- C3{是否发生循环依赖?} C3 --|是| D3[调用 getObject 创建代理br/存入二级缓存] C3 --|否| E3[三级缓存不调用br/代理在正常阶段创建] E3 -- F3[初始化后 AOP 创建代理br/BeanPostProcessor] end4.3 关键源码getEarlyBeanReference()// org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory protected Object getEarlyBeanReference(String beanName, RootBeanDefinition mbd, Object bean) { Object exposedObject bean; if (!mbd.isSynthetic() hasInstantiationAwareBeanPostProcessors()) { for (SmartInstantiationAwareBeanPostProcessor bp : getBeanPostProcessorCache().smartInstantiationAware) { // 如果需要 AOP 代理这里会提前创建代理对象 exposedObject bp.getEarlyBeanReference(exposedObject, beanName); } } return exposedObject; }面试话术三级缓存的 ObjectFactory 中调用的getEarlyBeanReference()会遍历所有SmartInstantiationAwareBeanPostProcessor如果该 Bean 需要 AOP 代理被 Transactional 或 Aspect 标注就会在这里提前创建代理对象。如果不需要代理直接返回原始 Bean。这就是延迟创建代理的含义。4.4 总结问题二级缓存三级缓存能否解决无 AOP 的循环依赖✅✅能否解决有 AOP 的循环依赖❌ 代理创建时机不对✅ 按需延迟创建无循环依赖时是否多余创建代理❌ 会提前创建✅ 不会设计理念简单直接延迟加载按需创建面试终极回答Spring 使用三级缓存而非二级缓存核心是为了处理 AOP 场景下的循环依赖。三级缓存的 ObjectFactory 实现了代理对象的延迟创建——只有在发生循环依赖时才提前生成代理没有循环依赖时代理在正常的初始化后阶段创建保证了代理创建的时机正确。五、构造器注入为何无法解决5.1 核心原因鸡生蛋问题构造器注入要求在实例化阶段就拿到依赖而 Spring 解决循环依赖的前提是先实例化再填充属性。构造器注入把这个前提打破了——A 的实例化依赖 BB 的实例化依赖 A双方都无法先实例化。创建 A需要 B 的构造器参数去创建 B需要 A 的构造器参数去创建 AA 正在创建中!抛出 BeanCurrentlyInCreationException5.2 源码层面的原因// org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory protected BeanWrapper createBeanInstance(String beanName, RootBeanDefinition mbd, Object[] args) { // 构造器注入在这里解析依赖 // 如果依赖的 Bean 尚未实例化会调用 getBean() // 但 getBean 又会回到 createBeanInstance → 死循环 Constructor?[] ctors determineConstructorsFromBeanPostProcessors(bd, beanName); // ... 解析构造器参数 // 此时 A 和 B 都还没实例化完成无法互相提供 }关键点三级缓存的暴露addSingletonFactory发生在createBeanInstance之后但构造器注入的依赖解析发生在createBeanInstance之中。也就是说三级缓存还没来得及存构造器就已经需要依赖了。5.3 构造器循环依赖的报错信息org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name serviceA defined in file [...]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.BeanCurrentlyInCreationException: Error creating bean with name serviceB: Requested bean is currently in creation: Is there an unresolvable circular reference?六、特殊场景分析6.1 Lazy 解决构造器循环依赖Component public class ServiceA { private final ServiceB serviceB; Autowired public ServiceA(Lazy ServiceB serviceB) { this.serviceB serviceB; } } Component public class ServiceB { private final ServiceA serviceA; Autowired public ServiceB(Lazy ServiceA serviceA) { this.serviceA serviceA; } }原理Lazy会让 Spring 注入一个代理对象而非真实 Bean。构造器阶段拿到的是代理对象的空壳不会触发真实 Bean 的创建。后续第一次调用代理对象的方法时代理对象才会去容器中获取真实 Bean此时真实 Bean 已经创建完成。6.2 Async 导致循环依赖失败Component public class ServiceA { Autowired private ServiceB serviceB; } Component public class ServiceB { Lazy Autowired private ServiceA serviceA; Async public void asyncMethod() { } }原因Async会给 ServiceB 创建 AOP 代理。在 ServiceB 的postProcessAfterInitialization阶段代理对象被创建。但这个代理对象和之前三级缓存中通过getEarlyBeanReference创建的早期引用不是同一个对象导致 Spring 发现最终对象和早期引用不一致抛出异常。解决方案在注入处加Lazy使用EnableAsync时设置proxyTargetClass trueSpring Boot 2.6 默认禁止循环依赖需通过spring.main.allow-circular-referencestrue开启6.3 原型 Bean 的循环依赖Component Scope(prototype) public class ServiceA { Autowired private ServiceB serviceB; } Component Scope(prototype) public class ServiceB { Autowired private ServiceA serviceA; }结论Spring不尝试解决原型 Bean 的循环依赖直接抛出异常。因为原型 Bean 每次获取都是新对象无法通过缓存机制管理。6.4 Spring Boot 2.6 默认禁止循环依赖Spring Boot 2.6 起默认禁止循环依赖# application.yml spring: main: allow-circular-references: false # 默认值为什么循环依赖本质上是设计问题Spring 团队认为开发者应该通过重构代码来消除循环依赖而不是依赖框架的补丁机制。禁止循环依赖能在开发阶段更早发现问题。如何开启设置spring.main.allow-circular-referencestrue。6.5 三种消除循环依赖的设计方案循环依赖 A-B-A如何消除?方案1: 提取公共逻辑方案2: 事件驱动解耦方案3: 中间人模式抽取 AB 共用逻辑到 ServiceCA-C, B-CA 发布事件, B 监听事件无需互相持有引用引入 Manager/CoordinatorA-Manager, B-Manager方案适用场景示例提取公共逻辑A 和 B 需要相同功能抽取 ServiceCA/B 都依赖 C事件驱动A 完成后通知 BA 发布ApplicationEventB 用EventListener监听中间人模式A 和 B 需要协调引入OrderService协调PaymentService和InventoryService七、自检Q1: 什么是循环依赖Spring 能解决哪些答循环依赖是两个或多个 Bean 互相持有对方引用。Spring 只能解决单例 Setter/字段注入的循环依赖构造器注入和原型 Bean 的循环依赖无法解决。Q2: 三级缓存分别是什么答一级缓存singletonObjects存放完整的 Bean二级缓存earlySingletonObjects存放早期暴露的 Bean已实例化但未完全初始化三级缓存singletonFactories存放 ObjectFactory用于延迟创建早期引用处理 AOPQ3: 为什么需要三级缓存二级不行吗答二级缓存在无循环依赖时会提前创建 AOP 代理导致代理创建时机错误。三级缓存的 ObjectFactory 实现了按需延迟创建——只有发生循环依赖时才调用 getObject() 创建代理没有循环依赖时代理在正常的 BeanPostProcessor 阶段创建。Q4: 构造器注入的循环依赖为什么无法解决答构造器注入的依赖解析发生在实例化阶段而三级缓存的暴露在实例化之后。也就是说还没来得及把 Bean 存入三级缓存构造器就已经需要依赖了形成死循环。Q5: Lazy 如何解决构造器循环依赖答Lazy注入的是代理对象而非真实 Bean。构造器拿到代理的空壳不会触发真实 Bean 的创建。后续调用方法时代理才去容器获取真实 Bean。核心源码路径速查类方法作用DefaultSingletonBeanRegistrygetSingleton(String, boolean)三级缓存查找逻辑DefaultSingletonBeanRegistryaddSingletonFactory()存入三级缓存DefaultSingletonBeanRegistryaddSingleton()存入一级缓存AbstractAutowireCapableBeanFactorydoCreateBean()暴露三级缓存的入口AbstractAutowireCapableBeanFactorygetEarlyBeanReference()三级缓存的 ObjectFactory 执行逻辑

相关文章:

Spring - 循环依赖

一、循环依赖概览1.1 什么是循环依赖?循环依赖是指两个或多个 Bean 之间互相持有对方引用,形成闭环。例如 A 依赖 B,B 又依赖 A。A 依赖 BB 依赖 A1.2 循环依赖的三种类型// 类型1:构造器注入的循环依赖(无法解决&…...

机械臂轨迹规划中的S型速度优化算法设计与实现

1. 机械臂轨迹规划的核心挑战 机械臂运动控制中最关键的问题之一,就是如何让机械臂在保证平稳运行的前提下,以最短时间完成指定轨迹。想象一下工厂里的机械臂在流水线上快速精准地抓取零件——这个看似简单的动作背后,隐藏着复杂的运动学计算…...

Linux/Android文件系统架构深度剖析

文章目录一、preface1、资料快车2、概述3、专业术语二、Linux文件系统架构1、文件系统框架图2、文件系统之块设备字符设备框架3、内核如何读取文件?4、文件系统类型1)持久文件系统1、本地文件系统2、网络文件系统2)运行时文件系统3&#xff0…...

双蒙皮声纳导流罩(Sonar Domes)技术情报报告

1. 概述 声纳导流罩(Sonar Dome)是安装在舰艇艏部或潜艇前端的流线型外壳,用于保护声纳换能器阵列,同时确保声学性能和水动力性能。现代声纳导流罩采用双蒙皮结构(Double-Skin Design),兼顾结构强度、轻量化、声学透明性和维护便捷性。 2. 双蒙皮结构设计特点 2.1 柯蒂…...

云凝结合计数器CNN粒子数浓度分析/python数据可视化

CCN-100是美国DMT公司(Drop Measurement Technologies)生产的一款经典仪器,专用于连续、实时测量大气中不同过饱和度下的CCN数浓度。它采用热梯度云室(Thermal Gradient Cloud Chamber)技术,模拟自然界中云…...

变深声纳(VDS)收放系统技术情报报告

1. 系统概述 变深声纳(Variable Depth Sonar, VDS)是现代反潜战(ASW)的关键传感器技术,通过将声纳拖体部署到舰艇下方一定深度,避开表层温跃层和舰艇自噪声,实现对常规潜艇的有效探测。VDS收放系统是确保声纳拖体安全部署、精确定位和可靠回收的核心机械系统。 2. 拖曳…...

Spring Boot 3.x强制JDK17?老项目迁移前必看的Java8兼容方案

Spring Boot 3.x强制JDK17?老项目迁移前必看的Java8兼容方案 对于许多企业级Java开发者来说,2023年是个分水岭——Spring Boot 3.x全面拥抱JDK17,官方Initializr默认不再提供Java8选项。但现实情况是,大量生产环境仍运行在JDK8上&…...

浅论虚荣心

浅论虚荣心虚荣心是人性中常见的一种心理倾向,是人们为了取得荣誉和引起普遍注意而表现出来的一种社会情感和心理状态。适度的虚荣心可以给生活带来激情,给工作带来动力,在一定条件下,它也能成为自尊心、自信心建立的促进剂——但…...

IDM 下载管理器 下载安装

链接: https://pan.baidu.com/s/1IJ4LrAAZCfVvPyZl9VVg8g 提取码: j9c9解压前请退出所有杀毒软件或添加排除项!!!此文件无毒,可放心使用!!!此文件为免费开源绿色软件,请勿利用于商业…...

23岁+计算机人注意!困在传统开发?这份大模型报告助你职场逆袭,薪资翻倍!

如果你是23岁以上的计算机相关从业者,正困在传统开发瓶颈里、想跳槽无优势、想转行怕踩坑,或是盯着职场晋升、薪资翻倍却找不到突破口,那这篇文章和这份重磅报告,一定要认真看完。 当下人工智能全面落地,大模型早已不是…...

应急响应-vulntarget-n-勒索病毒应急靶场

convert -f raw -O vmdk .\vuln_m-j6cegcrhehdcba0r5h4v_system.raw vuln_m-j6cegcrhehdcba0r5h4v_system.vmdk 将靶场的 raw 原始磁盘镜像,转换成 VMware 可以直接加载使用的 vmdk 虚拟硬盘文件。flag1先看一下history有记录,一条flag就在历史命令里fla…...

在Ubuntu里同时安装mozc和sogoupinyin输入法的后续故事

好久没有玩Ubuntu了。最近小龙虾真的是如火如荼的,想凑个热闹,就把16年的电脑革掉,安装上了Ubuntu 22.04.5 LTS。安装完了才想起来,我这台老电脑压根就没有独显,电脑自己的本地龙虾,是铁定装不上了。龙虾的…...

领英大规模账户攻击事件技术溯源与反钓鱼防御体系研究

摘要 2026 年 4 月初,全球职业社交平台 LinkedIn 被披露遭遇大规模账户安全威胁,涉及海量用户身份凭证与会话信息面临窃取、劫持风险,引发全球网络空间安全预警。本次攻击以社交工程为核心、结合浏览器插件扫描、评论区批量注入、短链接混淆、…...

手把手教你封装OCCT_Window:一个可复用的Qt Widget组件(附完整源码)

手把手教你封装OCCT_Window:打造高复用Qt 3D显示组件 在工业软件和CAD应用开发中,将Open CASCADE的3D显示能力无缝集成到Qt界面是一个常见需求。传统做法往往需要开发者深入理解OCCT的窗口系统与Qt的交互机制,导致大量重复劳动。本文将展示如…...

03-Linux网络故障排查:从DNS配置到防火墙设置的全面指南

1. 当Linux告诉你"Name or service not known"时 第一次在Linux终端看到"Name or service not known"这个错误提示时,我正急着要下载一个重要的软件包。那种感觉就像你明明知道朋友家的地址,导航却死活找不到路。这个看似简单的网络…...

Python MCP服务器开发面试必考题全解析:从协议设计到并发压测,97%候选人栽在这3个盲区

第一章:Python MCP服务器开发面试全景概览Python MCP(Model-Controller-Protocol)服务器并非标准框架术语,而是近年来在微服务与协议网关场景中逐渐形成的工程实践模式——强调以协议适配为核心、模型驱动行为、控制器协调生命周期…...

基于深度学习的轴承故障诊断:CNN-LSTM架构演进与核心代码逻辑拆解

基于深度学习的轴承故障诊断:CNN-LSTM架构演进与核心代码逻辑拆解前言 在设备健康管理(PHM)的实战中,面对凯斯西储大学(CWRU)轴承数据集,直接将几十万个采样点的振动信号塞给模型是行不通的。即…...

【稀缺首发】PyTorch 3.0静态图分布式训练性能基线报告(A100×8实测:静态图提速2.7×,通信开销下降63%)

第一章:PyTorch 3.0静态图分布式训练配置概览PyTorch 3.0 引入了原生静态图(Static Graph)支持,通过 torch.compile() 默认后端 inductor 与分布式运行时深度协同,显著提升多卡训练的启动速度与稳定吞吐。静态图模式下…...

CSMS详细学习,CIA网络安全接口协议和CSMS的关系

CSMS详细学习,CIA网络安全接口协议和CSMS的关系 一、CSMS的定义与核心目标 CSMS(Cybersecurity Management System) 是由 UN R155法规 强制要求建立的一套组织级网络安全管理体系。其本质是通过制度化的流程、策略和资源分配,确保…...

ai赋能开发:让快马平台智能生成带数据分析的dht11温湿度监测应用

最近在做一个智能家居相关的项目,需要用到DHT11温湿度传感器。本来以为就是简单读取数据显示一下,但突然想到能不能加点智能分析功能,让数据更有价值。正好发现了InsCode(快马)平台,它的AI辅助开发功能帮我省去了大量编码时间&…...

MySQL数据库(基础语法篇

MySQL数据库(基础语法篇 这份文档详细梳理了MySQL数据库的核心语法体系,涵盖了从基础的数据定义、操纵、查询,到进阶的多表连接、视图、存储过程以及最佳实践。 一、MySQL优势 MySQL作为世界上最流行的开源数据库之一,具有诸多显著特点与优势…...

新手福音:在wsl2中用快马生成你的第一个python命令行工具

最近在学WSL2开发环境搭建,发现对新手最头疼的不是写代码,而是配环境、记命令这些前期准备。好在发现了InsCode(快马)平台,用它生成的Python命令行工具项目特别适合练手,连我这种Linux小白都能半小时跑通全流程。记录下这个超适合…...

Agent可观测性工程:监控、追踪与告警的最佳实践

Agent可观测性工程:监控、追踪与告警的最佳实践 一、 引言 (Introduction) (一)钩子 (The Hook) 你是否有过这种令人抓狂的经历?凌晨三点,手机突然弹出刺耳的告警提示音,内容是“你的金融风控Agent集群延迟飙升至27秒,核心交易拒单率突破5‰阈值!”。你从床上弹起来,…...

Maxwell永磁体磁场仿真:从表面强度到空间分布的全流程解析

1. 永磁体磁场仿真入门指南 第一次接触永磁体磁场仿真时,我也被各种专业术语搞得晕头转向。后来在实际项目中才发现,掌握这项技能对电机设计、传感器开发等工作至关重要。Maxwell作为电磁场仿真领域的标杆软件,能帮助我们直观地看到肉眼看不见…...

HFSS 2023 R1实战:手把手教你从ADS优化到Wilkinson功分器建模(附完整模型文件)

HFSS 2023 R1实战:从ADS优化到Wilkinson功分器三维建模全流程解析 在射频工程领域,将电路仿真结果准确转化为三维电磁场模型是一个关键但常被忽视的环节。许多工程师在ADS中完成了理想的参数优化后,却对如何在HFSS中实现同等性能感到困惑。本…...

QT: 二维码生成与自定义渲染实战

1. 二维码基础与QT开发环境搭建 二维码本质上是用黑白矩形图案表示二进制数据的图形化编码方案。相比传统条形码,它的核心优势在于二维方向上的数据存储能力,以及强大的容错机制。我在实际项目中发现,即使用户拍摄的二维码有部分污损或遮挡&a…...

17步拆解!一张图看懂AIAgent全流程,轻松掌握大模型应用开发核心!

本文通过一张图详细拆解了AIAgent从用户提问到结果返回的17步全流程,深入探讨了提示词、Agent、大模型、MCP和工具等关键要素在智能体架构中的作用。文章揭示了它们如何共同构建从自然语言意图到智能决策、工具执行再到结果反馈的完整闭环,为开发者提供了…...

4道高频面试题,吃透时间复杂度(递归_堆_贪心_快排)

4道高频面试题,吃透时间复杂度(递归/堆/贪心/快排) 前言:时间复杂度是算法面试的“必考题”,也是区分初级与中级开发者的核心考点。很多开发者能写出正确的算法代码,却无法清晰、严谨地分析其时间复杂度&am…...

音频算法可视化实战:用Android自定义View绘制专业级EQ/DRC曲线图

音频算法可视化实战:用Android自定义View绘制专业级EQ/DRC曲线图 在音频处理领域,EQ(均衡器)和DRC(动态范围控制)是两大核心算法。对于已经掌握这些算法原理的开发者来说,如何将它们直观地呈现给…...

从MATLAB R2022b升级到R2024a,我的Python脚本为啥跑不起来了?

从MATLAB R2022b升级到R2024a:Python混合编程兼容性危机与系统化解决方案 上周三凌晨两点,当我在服务器上完成MATLAB R2024a的升级部署后,原本稳定运行的数据分析流水线突然崩溃——那些精心编写的Python-MATLAB混合脚本像多米诺骨牌一样接连…...