手写Spring IoC:注解+反射打造轻量级容器

手写Spring IoC:注解+反射打造轻量级容器

深入理解Spring IoC核心原理,通过注解和反射机制手写一个简易版IoC容器,掌握依赖注入的本质。

1. 引言:Spring IoC的魔力

在Spring框架中,IoC(控制反转)和DI(依赖注入)是最核心的概念。只需一个@Autowired注解,Spring就能自动帮我们注入依赖对象,这背后的原理是什么?

本文将通过注解+反射的方式,手写一个简易版Spring IoC容器,让你深入理解:

  • 注解是如何被扫描和解析的
  • Bean是如何被创建和管理的
  • 依赖注入是如何实现的
  • Spring容器的运行机制

Spring IoC容器架构

1.1 为什么要手写IoC?

  • 理解原理- 知其然更知其所以然
  • 面试必备- Spring IoC是面试高频考点
  • 提升能力- 掌握反射、注解等核心技术
  • 框架选型- 理解框架设计思想

2. 核心概念:IoC、DI、注解、反射

2.1 控制反转(IoC)

传统方式:对象自己创建依赖

public class UserService { private UserDao userDao = new UserDaoImpl(); // 主动创建 }

IoC方式:对象由容器创建和注入

public class UserService { @Autowired private UserDao userDao; // 被动接收 }

控制反转就是把对象创建和依赖管理的控制权,从应用代码转移到IoC容器。

2.2 依赖注入(DI)

依赖注入是IoC的实现方式,有三种注入方式:

① 构造器注入

@Component public class UserService { private final UserDao userDao; @Autowired public UserService(UserDao userDao) { this.userDao = userDao; } }

② Setter注入

@Component public class UserService { private UserDao userDao; @Autowired public void setUserDao(UserDao userDao) { this.userDao = userDao; } }

③ 字段注入(最常用)

@Component public class UserService { @Autowired private UserDao userDao; }

2.3 Java注解

注解是Java 5引入的元数据标记机制。

// 定义注解 @Retention(RetentionPolicy.RUNTIME) // 运行时保留 @Target(ElementType.TYPE) // 作用于类 public @interface Component { String value() default ""; } // 使用注解 @Component("userService") public class UserService { }

2.4 Java反射

反射允许程序在运行时动态获取类信息并操作对象。

// 加载类 Class<?> clazz = Class.forName("com.example.UserService"); // 检查注解 if (clazz.isAnnotationPresent(Component.class)) { Component component = clazz.getAnnotation(Component.class); String beanName = component.value(); } // 创建实例 Object instance = clazz.getDeclaredConstructor().newInstance(); // 获取字段 Field[] fields = clazz.getDeclaredFields(); // 设置字段值 field.setAccessible(true); field.set(instance, value);

3. 第一步:定义核心注解

Spring核心注解

首先定义我们自己的注解,模拟Spring的核心注解。

3.1 @Component注解

package com.myspring.annotation; import java.lang.annotation.*; /** * 标记组件类,类似Spring的@Component */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface Component { /** * Bean名称,默认为类名首字母小写 */ String value() default ""; }

3.2 @Autowired注解

package com.myspring.annotation; import java.lang.annotation.*; /** * 自动注入依赖,类似Spring的@Autowired */ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.FIELD, ElementType.METHOD, ElementType.CONSTRUCTOR}) public @interface Autowired { /** * 是否必须注入 */ boolean required() default true; }

3.3 @Qualifier注解

package com.myspring.annotation; import java.lang.annotation.*; /** * 指定要注入的Bean名称 */ @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.FIELD, ElementType.PARAMETER}) public @interface Qualifier { String value(); }

3.4 @Scope注解

package com.myspring.annotation; import java.lang.annotation.*; /** * 指定Bean的作用域 */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.TYPE) public @interface Scope { String value() default "singleton"; }

4. 第二步:实现包扫描器

注解扫描 流程

包扫描器负责扫描指定包下的所有类,找出带有@Component注解的类。

4.1 ClassScanner类

package com.myspring.core; import com.myspring.annotation.Component; import java.io.File; import java.net.URL; import java.util.ArrayList; import java.util.List; /** * 类扫描器:扫描指定包下的所有类 */ public class ClassScanner { /** * 扫描指定包下带有@Component注解的类 * * @param basePackage 基础包路径,如"com.example" * @return 带有@Component注解的Class列表 */ public static List<Class<?>> scanComponents(String basePackage) { List<Class<?>> classList = new ArrayList<>(); try { // 将包名转换为路径 String packagePath = basePackage.replace('.', '/'); // 获取包的URL路径 ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); URL resource = classLoader.getResource(packagePath); if (resource == null) { System.out.println("包路径不存在: " + basePackage); return classList; } // 获取包的文件路径 File packageDir = new File(resource.getFile()); // 递归扫描所有类文件 scanClasses(packageDir, basePackage, classList); } catch (Exception e) { e.printStackTrace(); } return classList; } /** * 递归扫描目录下的所有类文件 */ private static void scanClasses(File dir, String packageName, List<Class<?>> classList) { if (!dir.exists() || !dir.isDirectory()) { return; } File[] files = dir.listFiles(); if (files == null) { return; } for (File file : files) { if (file.isDirectory()) { // 递归扫描子目录 scanClasses(file, packageName + "." + file.getName(), classList); } else if (file.getName().endsWith(".class")) { try { // 获取类名 String className = packageName + "." + file.getName().replace(".class", ""); // 加载类 Class<?> clazz = Class.forName(className); // 检查是否有@Component注解 if (clazz.isAnnotationPresent(Component.class)) { classList.add(clazz); System.out.println("扫描到组件: " + className); } } catch (ClassNotFoundException e) { e.printStackTrace(); } } } } }

5. 第三步:创建Bean工厂

Bean工厂负责存储和管理所有的Bean实例。

5.1 BeanDefinition类

package com.myspring.core; /** * Bean定义信息 */ public class BeanDefinition { private String beanName; private Class<?> beanClass; private String scope; private Object singletonInstance; public BeanDefinition(String beanName, Class<?> beanClass, String scope) { this.beanName = beanName; this.beanClass = beanClass; this.scope = scope; } // Getter和Setter方法 public String getBeanName() { return beanName; } public Class<?> getBeanClass() { return beanClass; } public String getScope() { return scope; } public Object getSingletonInstance() { return singletonInstance; } public void setSingletonInstance(Object instance) { this.singletonInstance = instance; } }

5.2 BeanFactory类

package com.myspring.core; import com.myspring.annotation.Component; import com.myspring.annotation.Scope; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; /** * Bean工厂:创建和管理Bean实例 */ public class BeanFactory { // 存储Bean定义信息 private Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(); /** * 注册Bean定义 */ public void registerBeanDefinition(Class<?> clazz) { // 获取Bean名称 Component component = clazz.getAnnotation(Component.class); String beanName = component.value(); if (beanName.isEmpty()) { // 默认使用类名首字母小写 beanName = toLowerFirstCase(clazz.getSimpleName()); } // 获取作用域 String scope = "singleton"; if (clazz.isAnnotationPresent(Scope.class)) { Scope scopeAnnotation = clazz.getAnnotation(Scope.class); scope = scopeAnnotation.value(); } // 创建BeanDefinition并注册 BeanDefinition beanDefinition = new BeanDefinition(beanName, clazz, scope); beanDefinitionMap.put(beanName, beanDefinition); System.out.println("注册Bean: " + beanName + ", 作用域: " + scope); } /** * 获取Bean实例 */ public Object getBean(String beanName) { BeanDefinition beanDefinition = beanDefinitionMap.get(beanName); if (beanDefinition == null) { throw new RuntimeException("Bean不存在: " + beanName); } // 单例模式 if ("singleton".equals(beanDefinition.getScope())) { Object instance = beanDefinition.getSingletonInstance(); if (instance == null) { instance = createBean(beanDefinition); beanDefinition.setSingletonInstance(instance); } return instance; } // 原型模式:每次都创建新实例 return createBean(beanDefinition); } /** * 根据类型获取Bean */ public Object getBean(Class<?> clazz) { for (BeanDefinition bd : beanDefinitionMap.values()) { if (clazz.isAssignableFrom(bd.getBeanClass())) { return getBean(bd.getBeanName()); } } throw new RuntimeException("Bean不存在: " + clazz.getName()); } /** * 创建Bean实例 */ private Object createBean(BeanDefinition beanDefinition) { try { Class<?> clazz = beanDefinition.getBeanClass(); Object instance = clazz.getDeclaredConstructor().newInstance(); System.out.println("创建Bean实例: " + beanDefinition.getBeanName()); return instance; } catch (Exception e) { throw new RuntimeException("创建Bean失败: " + beanDefinition.getBeanName(), e); } } /** * 首字母小写 */ private String toLowerFirstCase(String str) { char[] chars = str.toCharArray(); chars[0] += 32; return String.valueOf(chars); } /** * 获取所有Bean名称 */ public Map<String, BeanDefinition> getBeanDefinitions() { return beanDefinitionMap; } }

6. 第四步:实现依赖注入

依赖注入流程

依赖注入是IoC容器的核心功能,通过反射自动为Bean注入依赖。

6.1 DependencyInjector类

package com.myspring.core; import com.myspring.annotation.Autowired; import com.myspring.annotation.Qualifier; import java.lang.reflect.Field; /** * 依赖注入器:为Bean注入依赖 */ public class DependencyInjector { private BeanFactory beanFactory; public DependencyInjector(BeanFactory beanFactory) { this.beanFactory = beanFactory; } /** * 为所有Bean执行依赖注入 */ public void injectDependencies() { for (BeanDefinition bd : beanFactory.getBeanDefinitions().values()) { Object bean = beanFactory.getBean(bd.getBeanName()); injectBean(bean); } } /** * 为单个Bean注入依赖 */ public void injectBean(Object bean) { Class<?> clazz = bean.getClass(); // 获取所有字段 Field[] fields = clazz.getDeclaredFields(); for (Field field : fields) { // 检查是否有@Autowired注解 if (!field.isAnnotationPresent(Autowired.class)) { continue; } Autowired autowired = field.getAnnotation(Autowired.class); try { // 确定要注入的Bean Object dependency = null; // 检查是否有@Qualifier指定Bean名称 if (field.isAnnotationPresent(Qualifier.class)) { Qualifier qualifier = field.getAnnotation(Qualifier.class); String beanName = qualifier.value(); dependency = beanFactory.getBean(beanName); } else { // 根据类型查找Bean dependency = beanFactory.getBean(field.getType()); } // 反射设置字段值 field.setAccessible(true); field.set(bean, dependency); System.out.println("注入依赖: " + clazz.getSimpleName() + "." + field.getName()); } catch (Exception e) { if (autowired.required()) { throw new RuntimeException("依赖注入失败: " + clazz.getSimpleName() + "." + field.getName(), e); } } } } }

7. 第五步:完善生命周期

Bean生命周期

7.1 生命周期注解

package com.myspring.annotation; import java.lang.annotation.*; /** * Bean初始化后调用 */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface PostConstruct { } package com.myspring.annotation; import java.lang.annotation.*; /** * Bean销毁前调用 */ @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.METHOD) public @interface PreDestroy { }

7.2 生命周期管理器

package com.myspring.core; import com.myspring.annotation.PostConstruct; import com.myspring.annotation.PreDestroy; import java.lang.reflect.Method; /** * Bean生命周期管理器 */ public class LifecycleManager { /** * 执行初始化方法 */ public static void invokeInitMethod(Object bean) { Class<?> clazz = bean.getClass(); Method[] methods = clazz.getDeclaredMethods(); for (Method method : methods) { if (method.isAnnotationPresent(PostConstruct.class)) { try { method.setAccessible(true); method.invoke(bean); System.out.println("执行初始化方法: " + clazz.getSimpleName() + "." + method.getName()); } catch (Exception e) { throw new RuntimeException("初始化方法执行失败", e); } } } } /** * 执行销毁方法 */ public static void invokeDestroyMethod(Object bean) { Class<?> clazz = bean.getClass(); Method[] methods = clazz.getDeclaredMethods(); for (Method method : methods) { if (method.isAnnotationPresent(PreDestroy.class)) { try { method.setAccessible(true); method.invoke(bean); System.out.println("执行销毁方法: " + clazz.getSimpleName() + "." + method.getName()); } catch (Exception e) { e.printStackTrace(); } } } } }

8. 完整示例:使用手写IoC

手写IoC实现步骤

8.1 创建ApplicationContext

package com.myspring.core; import java.util.List; /** * 应用上下文:整合所有功能 */ public class ApplicationContext { private BeanFactory beanFactory; private DependencyInjector injector; public ApplicationContext(String basePackage) { // 1. 创建Bean工厂 beanFactory = new BeanFactory(); // 2. 扫描组件 System.out.println("========== 开始扫描组件 =========="); List<Class<?>> componentClasses = ClassScanner.scanComponents(basePackage); // 3. 注册Bean定义 System.out.println("\n========== 注册Bean定义 =========="); for (Class<?> clazz : componentClasses) { beanFactory.registerBeanDefinition(clazz); } // 4. 实例化所有单例Bean System.out.println("\n========== 实例化单例Bean =========="); for (BeanDefinition bd : beanFactory.getBeanDefinitions().values()) { if ("singleton".equals(bd.getScope())) { beanFactory.getBean(bd.getBeanName()); } } // 5. 依赖注入 System.out.println("\n========== 执行依赖注入 =========="); injector = new DependencyInjector(beanFactory); injector.injectDependencies(); // 6. 执行初始化方法 System.out.println("\n========== 执行初始化方法 =========="); for (BeanDefinition bd : beanFactory.getBeanDefinitions().values()) { Object bean = beanFactory.getBean(bd.getBeanName()); LifecycleManager.invokeInitMethod(bean); } System.out.println("\n========== IoC容器启动完成 ==========\n"); } /** * 获取Bean */ public Object getBean(String beanName) { return beanFactory.getBean(beanName); } /** * 根据类型获取Bean */ public <T> T getBean(Class<T> clazz) { return (T) beanFactory.getBean(clazz); } /** * 关闭容器 */ public void close() { System.out.println("\n========== 关闭IoC容器 =========="); for (BeanDefinition bd : beanFactory.getBeanDefinitions().values()) { Object bean = beanFactory.getBean(bd.getBeanName()); LifecycleManager.invokeDestroyMethod(bean); } } }

8.2 编写测试类

package com.example.dao; import com.myspring.annotation.Component; @Component public class UserDao { public void save() { System.out.println("UserDao: 保存用户数据"); } } package com.example.service; import com.example.dao.UserDao; import com.myspring.annotation.Autowired; import com.myspring.annotation.Component; import com.myspring.annotation.PostConstruct; import com.myspring.annotation.PreDestroy; @Component public class UserService { @Autowired private UserDao userDao; public void register(String username) { System.out.println("UserService: 注册用户 " + username); userDao.save(); } @PostConstruct public void init() { System.out.println("UserService初始化完成"); } @PreDestroy public void destroy() { System.out.println("UserService准备销毁"); } } package com.example; import com.example.service.UserService; import com.myspring.core.ApplicationContext; /** * 测试类 */ public class Main { public static void main(String[] args) { // 创建IoC容器 ApplicationContext context = new ApplicationContext("com.example"); // 获取Bean并使用 UserService userService = context.getBean(UserService.class); userService.register("张三"); // 关闭容器 context.close(); } }

8.3 运行输出

========== 开始扫描组件 ========== 扫描到组件: com.example.dao.UserDao 扫描到组件: com.example.service.UserService ========== 注册Bean定义 ========== 注册Bean: userDao, 作用域: singleton 注册Bean: userService, 作用域: singleton ========== 实例化单例Bean ========== 创建Bean实例: userDao 创建Bean实例: userService ========== 执行依赖注入 ========== 注入依赖: UserService.userDao ========== 执行初始化方法 ========== 执行初始化方法: UserService.init UserService初始化完成 ========== IoC容器启动完成 ========== UserService: 注册用户 张三 UserDao: 保存用户数据 ========== 关闭IoC容器 ========== 执行销毁方法: UserService.destroy UserService准备销毁

9. 总结

9.1 核心要点

通过手写IoC容器,我们深入理解了:

  1. 注解机制- 使用@Retention@Target定义注解
  2. 反射技术- 类加载、实例创建、字段注入
  3. 扫描解析- 递归扫描包路径,解析注解信息
  4. Bean管理- 单例/原型模式,Bean定义存储
  5. 依赖注入- 自动查找和注入依赖对象
  6. 生命周期- 初始化和销毁回调方法

9.2 与Spring IoC的对比

功能手写版本Spring IoC
注解扫描简单递归高性能ASM字节码扫描
Bean管理Map存储多级缓存+循环依赖处理
依赖注入字段注入字段+构造器+Setter
作用域singleton/prototype更多作用域
AOP支持完整AOP框架
性能优化基础大量优化策略

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

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

相关文章

类型断言:强制类型转换的技巧

类型断言&#xff1a;强制类型转换的技巧 欢迎继续本专栏的第八篇文章。在前几期中&#xff0c;我们已逐步建立了 TypeScript 类型系统的坚实基础&#xff0c;涵盖了基本类型、特殊类型、枚举&#xff0c;以及数组和元组的处理。今天&#xff0c;我们将深入探讨类型断言这一关键…

大数据与财务管理专业就业岗位方向

2026年大专大数据与财务管理专业毕业生可选择的就业岗位涵盖数据分析、财务、金融科技等多个领域。该专业结合了大数据技术与财务管理知识&#xff0c;培养具备数据处理能力和财务分析能力的复合型人才。以下是详细的就业方向及岗位分析。数据分析类岗位岗位名称岗位职责技能要…

敏捷冲刺计划完全指南:理论框架、实践方法与工具体系

你大概率参加过这样的冲刺计划会&#xff1a;一屋子人对着Jira看板&#xff0c;产品经理念需求&#xff0c;工程师估算时间&#xff0c;最后列出一堆“理想情况”下能完成的任务。结果两周后发现&#xff1a;有的卡在依赖上&#xff0c;有的越做越大&#xff0c;还有的做完才发…

2kW 单向 Boost PFC + 全桥 LLC 串联谐振开关电源的 Matlab/Simulink 仿真探索

单向Boost PFC全桥LLC串联谐振开关电源Matlab/simulink仿真模型 2kw功率&#xff0c;输出48V&#xff0c;谐振频率100k LLC使用输出电压闭环/PFM控制最近在研究开关电源的小伙伴们&#xff0c;一定对功率因数校正&#xff08;PFC&#xff09;和 LLC 谐振变换器不陌生。今天就来…

贝佐斯/比尔盖茨/英伟达/英特尔等押注,NASA工程师带队打造通用机器人大脑,公司估值达20亿美元

在大模型可以从互联网、图像库和海量文本中「无限生长」的今天&#xff0c;机器人却被困在另一个世界——真实世界的数据极度稀缺、昂贵且不可复用。Business Insider 曾发布过一则看似轻巧却又极具洞察力的报道&#xff0c;「AI 机器人面临数据荒&#xff0c;一家初创公司找到…

WBS工作分解结构:从0掌握项目拆解核心方法与工具实战

如果你接过一个“三个月后上线新版本”或者“半年内完成系统重构”的任务&#xff0c;就知道那种感觉&#xff1a;目标很大&#xff0c;时间很长&#xff0c;但不知道怎么开始。WBS&#xff08;工作分解结构&#xff09;就是解决这个问题的——它不是复杂的理论&#xff0c;而是…

基于Java的仓库管理系统设计与实现

第3章 系统分析 为满足用户的需求&#xff0c;本章分析系统开发的可行性&#xff0c;将从技术和操作等方面来判断&#xff0c;然后通过需求分析、系统流程分析来确定仓库管理系统设计与实现的功能[7]。 3.1 技术可行性分析 仓库管理系统设计与实现在使用电脑和信息分析系统这些…

特斯拉Model3智能网联汽车自动驾驶虚拟教学实训软件

在职业教育的创新之路上&#xff0c;我们始终致力于将前沿技术转化为可触达的教学资源。今天&#xff0c;我们很荣幸向各位教育伙伴介绍一款专为智能网联汽车教学设计的虚拟实训软件——以特斯拉Model3为原型&#xff0c;融合理实一体的教学理念&#xff0c;助力课堂焕发新的活…

【vLLM 学习】Rlhf

vLLM 是一款专为大语言模型推理加速而设计的框架&#xff0c;实现了 KV 缓存内存几乎零浪费&#xff0c;解决了内存管理瓶颈问题。 更多 vLLM 中文文档及教程可访问 →vllm.hyper.ai/ *在线运行 vLLM 入门教程&#xff1a;零基础分步指南 源码 examples/offline_inference/r…

【光子AI / Photon AI】整理2021~2026 在 AI Agent、Multi-Agent Systems、多智能体学习、多智能体强化学习、协同智能/代理型智能体 等方向的 Papers

【光子AI / Photon AI】整理2021~2026 在 AI Agent、Multi-Agent Systems、多智能体学习、多智能体强化学习、协同智能/代理型智能体 等方向的 Papers 文章目录 【光子AI / Photon AI】整理2021~2026 在 AI Agent、Multi-Agent Systems、多智能体学习、多智能体强化学习、协同智…

枚举类型:常量集合的优雅管理

枚举类型&#xff1a;常量集合的优雅管理 欢迎继续本专栏的第七篇文章。在前几期中&#xff0c;我们已逐步深入 TypeScript 的类型系统&#xff0c;涵盖了基本类型、特殊类型如 any、unknown、void 和 never&#xff0c;以及 object 的处理。今天&#xff0c;我们将专注于枚举&…

Demo 骗了所有人?一做就会,一用就废!多模态 RAG 跨不过去的这道坎,看透了!

前言 近年来&#xff0c;GPT-4V、Gemini Pro Vision 等多模态大模型快速兴起&#xff0c;将图像、文本、音频等多种数据类型统一理解的能力&#xff0c;拓展到了搜索问答、辅助诊疗、法律检索等更复杂的任务场景中。 相比传统大语言模型&#xff08;LLMs&#xff09;&#xf…

无人值守智能污水处理控制系统:威纶通触摸屏与西门子PLC协同运行,真实工程项目稳定运行一年多供...

无人值守污水处理控制系统。 威纶通触摸屏与西门子200smart PLC编写的智能污水处理控制系统&#xff0c;带图纸&#xff0c;带PLC程序&#xff0c;触摸屏画面&#xff0c;控制要求&#xff0c;工艺流程&#xff0c;真实工程项目&#xff0c;已稳定运行一年多。 供大家学习参考在…

通过合理建模与架构设计,90% 的“JOIN 需求”可转化为 ES 原生支持的高效查询。

“通过合理建模与架构设计&#xff0c;90% 的‘JOIN 需求’可转化为 ES 原生支持的高效查询” 这一论断&#xff0c;是 Elasticsearch 工程实践的核心思想&#xff0c;其本质是用数据建模的前期成本&#xff0c;换取查询性能的指数级提升。一、建模范式&#xff1a;ES 的三大反…

‌测试教育路径:大学课程 vs 自学——2026年软件测试从业者专业成长指南

核心结论&#xff1a;能力为王&#xff0c;路径可选‌ 在2026年的中国软件测试行业&#xff0c;‌学历不再是职业发展的决定性门槛&#xff0c;工程能力与持续学习力才是晋升的核心引擎‌。无论是大学科班出身&#xff0c;还是自学转型者&#xff0c;只要掌握自动化测试、接口…

90%的程序员都在错误选择Embedding模型!6步评估框架+代码实战,让你避开所有坑,小白也能秒变向量专家!

通过通过将原始输入转换为固定大小的高维向量&#xff0c;捕捉语义信息&#xff0c;embedding&#xff08;嵌入&#xff09;模型在构建RAG、推荐系统&#xff0c;甚至自动驾驶的模型训练过程中都产生着至关重要的影响。 即使 OpenAI、Meta 和 Google 等科技巨头&#xff0c;也…

基于遗传算法优化的VMD信号去噪算法:样本熵与信噪比双重适应度函数提升信噪比及故障诊断特征提取研究

Matlab 基于遗传算法优化的VMD信号去噪算法 创新点&#xff1a;基于样本熵作为适应度函数 创新点2&#xff1a;基于信噪比作为适应度函数 提高信噪比 本人研究方向信号处理特征提取与故障诊断算法轴承振动信号中的微弱冲击特征总是被噪声淹没&#xff0c;这给旋转机械故障诊断…

测试人员压力管理:构建可持续的截止日期应对框架——面向软件质量守护者的专业生存指南

引言&#xff1a;被压缩的时间与被放大的责任 在敏捷开发与DevOps普及的浪潮中&#xff0c;测试工程师站在质量防线的最后关卡。IBM研究显示&#xff0c;78%的测试人员经历过程度不同的截止日期焦虑&#xff08;2025&#xff09;&#xff0c;而因时间压力导致的漏测问题占生产…

美国地产交易被AI大模型颠覆,RAG+混合搜索效率提升40%,程序员都在学!

在中国&#xff0c;买一套房&#xff0c;除了要有钱&#xff0c;还要看居住证、看社保、看户籍地&#xff1b;要关注当地限购政策&#xff0c;关注交易税&#xff0c;关注银行贷款、资金审核、税率变化……各种乱七八糟的文件与政策看得人头晕眼花&#xff1f; 其实美国也一样…

S32K144 Bootloader开发实战:CAN与串口双剑合璧

S32K144的bootloader&#xff0c;包括CAN和串口的&#xff0c;上 S32K144的bootloader&#xff0c;包括CAN和串口的&#xff0c;上下位机全部开源&#xff0c;提供使用指导和有限的代码解释&#xff0c;仅供学习使用&#xff0c;无uds&#xff0c;无uds&#xff0c;无uds&#…