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

Spring Boot 依赖注入与Bean管理:JavaConfig如何取代XML?

大家好呀!今天我们来聊一个超级实用的技术话题 —— Spring Boot 中的依赖注入和Bean管理,特别是JavaConfig是如何一步步取代XML配置的。我知道很多小伙伴一听到"依赖注入"、"Bean管理"这些词就头大,别担心!我会用最简单的方式,就像教小朋友一样,带你彻底搞懂这些概念!😊

📚 第一章:什么是依赖注入?先来个生活小例子!

想象一下,你是一个小厨师👨🍳,要做一道美味的番茄炒蛋🍳。你需要什么呢?需要番茄、鸡蛋、油、盐对吧?这些"材料"就是你的"依赖"!

传统方式:你自己去菜市场买番茄、去养鸡场找鸡蛋、去超市买油和盐…累不累?😫

依赖注入方式:有个神奇的冰箱(Spring容器),里面已经准备好了所有材料,你只需要说"我要做番茄炒蛋",冰箱就自动把材料给你准备好!太方便了吧!😍

// 传统方式:自己创建所有依赖
Tomato tomato = new Tomato();
Egg egg = new Egg();
Oil oil = new Oil();
Salt salt = new Salt();
ScrambledEggWithTomato dish = new ScrambledEggWithTomato(tomato, egg, oil, salt);// 依赖注入方式:告诉Spring你需要什么,它自动给你
@Autowired
ScrambledEggWithTomato dish;  // Spring会自动把材料准备好并组装好这道菜!

看到区别了吗?依赖注入(Dependency Injection, DI)就是把对象所需要的其他对象(依赖)自动"注入"给它,而不是让它自己创建。这样代码更干净、更灵活!👍

🧩 第二章:什么是Bean?为什么需要管理它们?

在Spring的世界里,Bean就是由Spring容器管理的对象。就像冰箱里的食材一样,都是被冰箱(Spring容器)管理着的。

为什么需要管理Bean呢? 🤔

  1. 控制反转(IoC):对象的创建和管理权从程序员手里转交给了Spring容器
  2. 单例管理:确保某些重要的对象只有一个实例(比如数据库连接)
  3. 依赖解析:自动处理对象之间的复杂依赖关系
  4. 生命周期管理:控制对象的创建、初始化、销毁等过程

以前,我们用XML文件来配置这些Bean,就像写购物清单一样:

这种方式虽然能工作,但有好多问题:

  • XML文件会变得超级大,难以维护 📜
  • 没有类型安全检查,容易写错 ❌
  • 配置和代码分离,跳来跳去看很麻烦 🔍
  • 重构困难,改个类名要到处改XML 😫

💎 第三章:JavaConfig闪亮登场!✨

于是,Spring 3.0引入了JavaConfig,就是用Java类来代替XML配置!这就像是用智能手机📱取代老式按键手机一样,是巨大的进步!

JavaConfig的核心是@Configuration注解。看看同样的配置用Java怎么写:

@Configuration
public class KitchenConfig {@Beanpublic Tomato tomato() {return new Tomato();}@Beanpublic Egg egg() {return new Egg();}@Beanpublic Oil oil() {return new Oil();}@Beanpublic Salt salt() {return new Salt();}@Beanpublic ScrambledEggWithTomato dish(Tomato tomato, Egg egg, Oil oil, Salt salt) {return new ScrambledEggWithTomato(tomato, egg, oil, salt);}
}

哇!是不是清晰多了?👏 JavaConfig的好处太多了:

类型安全:编译器会检查类型对不对
易于重构:IDE可以自动重命名
更强大:可以写逻辑、调用方法等
更简洁:很多配置可以用注解简化
与代码在一起:不用在XML和Java间跳来跳去

🏗️ 第四章:Spring Boot如何更进一步简化配置?

Spring Boot在JavaConfig基础上又做了超级多的自动化!它就像个智能助手🤖,能根据你的依赖自动配置很多东西。

Spring Boot的核心魔法:

  1. 自动配置(Auto-configuration):根据classpath中的jar包自动配置Bean
  2. 起步依赖(Starter Dependencies):把常用依赖打包成"套餐"
  3. 条件化Bean(@Conditional):满足条件才创建Bean
  4. 属性配置(application.properties):外部化配置

举个例子,要配置一个数据库连接,以前要写一大堆:

@Configuration
public class DataSourceConfig {@Beanpublic DataSource dataSource() {DriverManagerDataSource dataSource = new DriverManagerDataSource();dataSource.setDriverClassName("com.mysql.jdbc.Driver");dataSource.setUrl("jdbc:mysql://localhost:3306/mydb");dataSource.setUsername("root");dataSource.setPassword("password");return dataSource;}
}

而在Spring Boot中,只需要在application.properties中写:

spring.datasource.url=jdbc:mysql://localhost:3306/mydb
spring.datasource.username=root
spring.datasource.password=password
spring.datasource.driver-class-name=com.mysql.jdbc.Driver

Spring Boot会自动帮你创建DataSource的Bean!如果连这些都不想写,用H2内存数据库的话,甚至什么都不用配置!😲

🎯 第五章:依赖注入的三种主要方式

Spring提供了三种主要的依赖注入方式,就像给冰箱里的食材三种不同的包装方式:

1. 构造器注入 (最推荐!👍)

public class ScrambledEggWithTomato {private final Tomato tomato;private final Egg egg;private final Oil oil;private final Salt salt;// 通过构造方法注入public ScrambledEggWithTomato(Tomato tomato, Egg egg, Oil oil, Salt salt) {this.tomato = tomato;this.egg = egg;this.oil = oil;this.salt = salt;}
}

优点

  • 不可变(final字段)
  • 完全初始化的对象
  • 易于测试
  • Spring官方推荐

2. Setter方法注入

public class ScrambledEggWithTomato {private Tomato tomato;private Egg egg;private Oil oil;private Salt salt;// 通过setter方法注入public void setTomato(Tomato tomato) {this.tomato = tomato;}public void setEgg(Egg egg) {this.egg = egg;}// 其他setter...
}

适用场景

  • 可选依赖
  • 需要重新配置的依赖

3. 字段注入 (不推荐❌)

public class ScrambledEggWithTomato {@Autowiredprivate Tomato tomato;@Autowiredprivate Egg egg;@Autowiredprivate Oil oil;@Autowiredprivate Salt salt;
}

为什么不推荐

  • 难以测试(必须用Spring容器)
  • 隐藏了依赖关系
  • 不能声明为final

🌈 第六章:Bean的作用域 - 控制Bean的生命周期

Spring中的Bean有不同的作用域,就像食材有不同的保质期一样:

  1. Singleton(单例):默认作用域,整个应用只有一个实例 🌟

    @Bean
    @Scope("singleton")  // 可以省略,默认就是
    public Tomato tomato() {return new Tomato();
    }
    
  2. Prototype(原型):每次请求都创建一个新实例 🔄

    @Bean
    @Scope("prototype")
    public Egg egg() {return new Egg();  // 每次获取都会new一个新的
    }
    
  3. Request:每个HTTP请求一个实例 (Web) 🌐

  4. Session:每个HTTP会话一个实例 (Web) 💻

  5. Application:每个ServletContext一个实例 (Web) 🖥️

  6. WebSocket:每个WebSocket会话一个实例 (Web) 🕸️

如何选择?

  • 无状态的服务类通常用singleton
  • 有状态的类考虑用prototype
  • Web相关的作用域用于Web环境

🛠️ 第七章:高级话题 - 条件化Bean与Profile

有时候我们想根据不同的环境创建不同的Bean,比如开发环境和生产环境用不同的数据源。Spring提供了两种主要方式:

1. @Profile - 根据环境激活Bean

@Configuration
public class DataSourceConfig {@Bean@Profile("dev")  // 开发环境用H2内存数据库public DataSource devDataSource() {return new EmbeddedDatabaseBuilder().setType(EmbeddedDatabaseType.H2).addScript("classpath:schema.sql").build();}@Bean@Profile("prod")  // 生产环境用MySQLpublic DataSource prodDataSource() {DriverManagerDataSource dataSource = new DriverManagerDataSource();dataSource.setDriverClassName("com.mysql.jdbc.Driver");dataSource.setUrl("jdbc:mysql://prod-server:3306/mydb");dataSource.setUsername("prod-user");dataSource.setPassword("prod-password");return dataSource;}
}

激活profile的方式:

  • 命令行:--spring.profiles.active=dev
  • 配置文件:spring.profiles.active=dev
  • 环境变量:SPRING_PROFILES_ACTIVE=dev

2. @Conditional - 更灵活的条件判断

@Bean
@Conditional(MyCustomCondition.class)  // 自定义条件
public DataSource dataSource() {// ...
}public class MyCustomCondition implements Condition {@Overridepublic boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {// 这里写判断逻辑,返回true才创建Beanreturn context.getEnvironment().containsProperty("custom.property");}
}

Spring Boot提供了很多现成的条件注解:

  • @ConditionalOnClass:类路径有指定类时生效
  • @ConditionalOnMissingBean:没有指定Bean时生效
  • @ConditionalOnProperty:有指定配置属性时生效
  • @ConditionalOnWebApplication:是Web应用时生效

🔄 第八章:Bean的生命周期回调

有时候我们需要在Bean创建或销毁时做一些事情,Spring提供了几种方式:

  1. 实现接口

    public class MyBean implements InitializingBean, DisposableBean {@Overridepublic void afterPropertiesSet() throws Exception {// 初始化逻辑}@Overridepublic void destroy() throws Exception {// 销毁逻辑}
    }
    
  2. 使用注解 (更推荐!):

    public class MyBean {@PostConstructpublic void init() {// 初始化逻辑}@PreDestroypublic void cleanup() {// 销毁逻辑}
    }
    
  3. 在@Bean注解中指定

    @Bean(initMethod = "init", destroyMethod = "cleanup")
    public MyBean myBean() {return new MyBean();
    }
    

执行顺序

  1. 构造函数
  2. @Autowired注入依赖
  3. @PostConstruct方法
  4. …使用Bean…
  5. @PreDestroy方法

🧠 第九章:常见问题与最佳实践

❓ 问题1:什么时候用@Component,什么时候用@Bean?

  • @Component:用在类上,让Spring自动扫描并创建Bean

    @Component
    public class MyService {// ...
    }
    
  • @Bean:用在@Configuration类的方法上,手动定义Bean创建逻辑

    @Configuration
    public class MyConfig {@Beanpublic MyService myService() {return new MyService();}
    }
    

经验法则

  • 自己写的类用@Component
  • 第三方库的类或需要复杂初始化的类用@Bean

❓ 问题2:循环依赖怎么办?

A依赖B,B又依赖A,这就形成了循环依赖。Spring能解决部分循环依赖,但最好避免!

解决方案

  1. 重新设计,打破循环
  2. 使用setter注入代替构造器注入
  3. 使用@Lazy延迟初始化
    @Component
    public class A {private final B b;public A(@Lazy B b) {  // 延迟初始化this.b = b;}
    }
    

❓ 问题3:如何选择XML和JavaConfig?

虽然JavaConfig是主流,但XML在以下情况仍有价值:

  • 遗留系统迁移
  • 需要在不修改代码的情况下更改配置
  • 某些复杂的Spring集成场景

但在新项目中,强烈建议使用JavaConfig!🎯

🚀 第十章:Spring Boot自动配置的魔法揭秘

Spring Boot的自动配置看起来像魔法,但其实原理很简单:

  1. @SpringBootApplication 是一个组合注解,包含:

    • @SpringBootConfiguration:标识这是配置类
    • @EnableAutoConfiguration:启用自动配置
    • @ComponentScan:自动扫描组件
  2. 自动配置原理

    • Spring Boot在spring-boot-autoconfigure.jar的META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports文件中定义了很多自动配置类
    • 这些类用@Conditional决定是否生效
    • 根据classpath中的类决定激活哪些配置
  3. 查看自动配置

    • 启动时添加--debug参数可以看到哪些自动配置生效了
    • 或者使用spring.autoconfigure.exclude排除某些自动配置
// 例如DataSourceAutoConfiguration的简化版
@Configuration
@ConditionalOnClass({ DataSource.class, EmbeddedDatabaseType.class })
@EnableConfigurationProperties(DataSourceProperties.class)
public class DataSourceAutoConfiguration {@Bean@ConditionalOnMissingBeanpublic DataSource dataSource(DataSourceProperties properties) {// 根据配置创建DataSource}
}

🎁 第十一章:自定义Starter - 把你的配置分享给他人

如果你想把自己的配置打包成一个Starter给别人用,非常简单:

  1. 创建一个普通的Spring Boot项目

  2. 添加你的@Configuration类

  3. 在src/main/resources/META-INF下创建:

    • spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports文件,写入你的配置类全名
    • additional-spring-configuration-metadata.json文件(可选,提供配置元数据)
  4. 打包发布,别人就可以通过引入你的starter来获得自动配置了!

📝 第十二章:总结 - JavaConfig vs XML 终极对决

特性JavaConfigXML配置
类型安全✅ 编译器检查❌ 运行时才发现错误
重构友好✅ IDE支持❌ 需要手动改
表达能力✅ 完整Java语法❌ 有限XML语法
灵活性✅ 可以写逻辑❌ 静态配置
可读性✅ 结构清晰❌ 嵌套复杂
配置集中度✅ 与代码一起❌ 分散在XML文件
学习曲线低(纯Java)中(特殊语法)
社区趋势主流逐渐淘汰

最终结论:在新项目中毫不犹豫选择JavaConfig!XML只应在维护旧系统时使用。🎉

🌟 第十三章:实战小练习

为了巩固知识,来做几个小练习吧!

练习1:创建一个配置类,定义以下Bean

  • 一个单例的UserService
  • 一个原型的Task
  • 一个依赖UserServiceProjectService

练习2:创建一个条件化Bean

  • 当系统属性"cache.enabled"=true时才创建CacheManager Bean

练习3:模拟一个Starter

  • 创建一个自动配置类,当classpath中有com.example.MyLib时自动配置MyLibAutoConfiguration

(答案可以在Spring官方文档或我的GitHub上找到哦~)

💖 最后的话

哇!不知不觉我们已经写了这么多内容!从最基础的依赖注入概念,到JavaConfig如何取代XML,再到Spring Boot的自动配置魔法,最后到创建自己的Starter。希望你现在对Spring的依赖注入和Bean管理有了清晰的认识!😊

记住,依赖注入的核心思想是"不要自己找依赖,让框架给你",而JavaConfig就是用Java代码清晰表达这种关系的最佳方式

如果你有任何问题,欢迎在评论区留言!我会尽力解答。也欢迎关注我的账号,我会持续分享更多Spring Boot和Java开发的干货内容!🚀

Happy Coding! 💻✨

推荐阅读文章

  • 由 Spring 静态注入引发的一个线上T0级别事故(真的以后得避坑)

  • 如何理解 HTTP 是无状态的,以及它与 Cookie 和 Session 之间的联系

  • HTTP、HTTPS、Cookie 和 Session 之间的关系

  • 什么是 Cookie?简单介绍与使用方法

  • 什么是 Session?如何应用?

  • 使用 Spring 框架构建 MVC 应用程序:初学者教程

  • 有缺陷的 Java 代码:Java 开发人员最常犯的 10 大错误

  • 如何理解应用 Java 多线程与并发编程?

  • 把握Java泛型的艺术:协变、逆变与不可变性一网打尽

  • Java Spring 中常用的 @PostConstruct 注解使用总结

  • 如何理解线程安全这个概念?

  • 理解 Java 桥接方法

  • Spring 整合嵌入式 Tomcat 容器

  • Tomcat 如何加载 SpringMVC 组件

  • “在什么情况下类需要实现 Serializable,什么情况下又不需要(一)?”

  • “避免序列化灾难:掌握实现 Serializable 的真相!(二)”

  • 如何自定义一个自己的 Spring Boot Starter 组件(从入门到实践)

  • 解密 Redis:如何通过 IO 多路复用征服高并发挑战!

  • 线程 vs 虚拟线程:深入理解及区别

  • 深度解读 JDK 8、JDK 11、JDK 17 和 JDK 21 的区别

  • 10大程序员提升代码优雅度的必杀技,瞬间让你成为团队宠儿!

  • “打破重复代码的魔咒:使用 Function 接口在 Java 8 中实现优雅重构!”

  • Java 中消除 If-else 技巧总结

  • 线程池的核心参数配置(仅供参考)

  • 【人工智能】聊聊Transformer,深度学习的一股清流(13)

  • Java 枚举的几个常用技巧,你可以试着用用

  • 由 Spring 静态注入引发的一个线上T0级别事故(真的以后得避坑)

  • 如何理解 HTTP 是无状态的,以及它与 Cookie 和 Session 之间的联系

  • HTTP、HTTPS、Cookie 和 Session 之间的关系

  • 使用 Spring 框架构建 MVC 应用程序:初学者教程

  • 有缺陷的 Java 代码:Java 开发人员最常犯的 10 大错误

  • Java Spring 中常用的 @PostConstruct 注解使用总结

  • 线程 vs 虚拟线程:深入理解及区别

  • 深度解读 JDK 8、JDK 11、JDK 17 和 JDK 21 的区别

  • 10大程序员提升代码优雅度的必杀技,瞬间让你成为团队宠儿!

  • 探索 Lombok 的 @Builder 和 @SuperBuilder:避坑指南(一)

  • 为什么用了 @Builder 反而报错?深入理解 Lombok 的“暗坑”与解决方案(二)

相关文章:

Spring Boot 依赖注入与Bean管理:JavaConfig如何取代XML?

大家好呀!今天我们来聊一个超级实用的技术话题 —— Spring Boot 中的依赖注入和Bean管理,特别是JavaConfig是如何一步步取代XML配置的。我知道很多小伙伴一听到"依赖注入"、"Bean管理"这些词就头大,别担心!我…...

AUTOSAR图解==>AUTOSAR_SWS_E2ETransformer

AUTOSAR E2E Transformer详解 基于AUTOSAR标准的端到端通信保护变换器技术解析 目录 1. E2E Transformer概述 1.1 E2E Transformer的作用1.2 功能特点1.3 应用场景限制 2. 模块架构 2.1 架构设计2.2 与其他模块的关系 3. 初始化与状态机 3.1 模块状态流转3.2 初始化与去初始化…...

从Archery到NineData:积加科技驱动数据库研发效能与数据安全双升级

积加科技作为国内领先的企业级数字化解决方案服务商,依托自研的 A4X 数字化平台(https://a4x.io/),专注于为全球范围内的视觉物联网(IoT)设备提供 PaaS/SaaS 服务。致力于运用 AI 技术赋能物联网世界的各类…...

hadoop和Yarn的基本介绍

Hadoop的三大结构及各自作用? Hadoop是一个由Apache基金会开发的分布式系统基础架构,主要用于处理大规模数据集的分布式存储和计算。Hadoop的三大核心结构是HDFS(Hadoop Distributed File System)、MapReduce和YARN(Y…...

神经接口安全攻防:从技术漏洞到伦理挑战

随着脑机接口(BCI)技术的快速发展,神经接口设备已从实验室走向消费市场。然而,2025年曝光的某品牌脑机接口设备漏洞(CVE-2025-3278)引发了行业对神经数据安全的深度反思。本文围绕神经接口安全的核心矛盾&a…...

云轴科技ZStack入选中国人工智能产业发展联盟《大模型应用交付供应商名录》

2025年4月8日至9日,中国人工智能产业发展联盟(以下简称AIIA)第十四次全体会议暨人工智能赋能新型工业化深度行(南京站)在南京召开。工业和信息化部科技司副司长杜广达,中国信息通信研究院院长、中国人工智能…...

SpringBoot项目异常处理

一、异常问题描述 进行添加员工测试的时候,服务端报错, 报错信息如下: java.sql.SQLIntegrityConstraintViolationException:主要就是因为在 employee 表结构中,我们针对于username字段,建立了唯一索引,添…...

机器学习05-CNN

CNN(卷积神经网络)学习文档 一、引言 卷积神经网络(Convolutional Neural Network,CNN)是深度学习中的一种重要网络结构,在图像识别、计算机视觉等领域取得了巨大成功。CNN 的设计灵感来源于生物视觉系统…...

Java Web 之 Servlet 100问

Filter 是什么? 在Java Web开发中,Filter(过滤器)是一种用于在请求到达目标资源(如Servlet、JSP)之前或响应返回客户端之前进行预处理和后处理的组件。Filter可以拦截请求和响应,执行特定的操作…...

z-library电子图书馆最新地址的查询方法

对于喜欢读书的伙伴们,应该都听说过z站(z-library),优点多多,缺点就是地址不稳定,经常会变化网站地址。然后我最近发现了一个工具,可以不间断更新官方可用的z站地址:电子书最新地址...

PyCharm入门导览

一、项目视图 项目视图位置如下所示: 项目视图是主要工具窗口之一。它包含项目目录、SDK特定的外部库和临时文件。点击带条纹的按 钮可以预览演示项目。也可以按Alt 1 打开。 二、Python解释器 点击右下角项目的名字,可以快速进入【Python解释器】界面…...

算法题(127):最大子段和

审题: 本题需要我们找到n个整数中连续且非空的最大子段和 思路: 方法一:前缀和 我们的思路是将每个索引位置的最大子段和求出,然后用answer进行max维护,最后输出answer即可 最大子段和怎么求? 子段和 f[i]…...

物联网分层架构全解析:从感知到应用的智能生态构建

物联网分层架构一般可细分为感知层、网络层、平台层和应用层,以下是各层更详细的介绍: 一、感知层 1.功能 数据采集:利用各类传感器对物理世界的各种信息进行采集,包括环境参数(如温度、湿度、光照、气压等&#xf…...

系统架构师2025年论文通用模板

搭建自己的模板 1、项目选择与实施建议整理 ‌一、项目选择标准‌ ‌金额与周期要求‌:优先选择金额在 ‌200万以上‌ 的中大型商业项目,研发周期建议 ‌不少于8个月‌‌。避免选择小型项目(如金额低于100万、周期短于1年)‌。 …...

Flink 2.0 编译

文章目录 Flink 2.0 编译第一个问题 java 版本太低maven 版本太低maven 版本太高开始编译扩展多版本jdk 配置 Flink 2.0 编译 看到Flink2.0 出来了,想去玩玩,看看怎么样,当然第一件事,就是编译代码,但是没想到这么多问…...

Java线程的几种状态

线程状态我们在此介绍六种线程状态 1.NEW 2.RUNNABLE 3.TIMED_WAITING 4.BLOCKED 5.WAITING 6.TERMINATED 1.初始状态 (NEW) 当一个线程对象被创建但尚未调用 start() 方法时,线程处于初始状态。此时,线程还没有开始执行。 通俗的讲就是安排了工作但是…...

2025年03月中国电子学会青少年软件编程(Python)等级考试试卷(一级)真题

青少年软件编程(Python)等级考试试卷(一级) 分数:100 题数:37 答案解析:https://blog.csdn.net/qq_33897084/article/details/147335019?spm1001.2014.3001.5501 一、单选题(共25题&#xff0…...

「数据可视化 D3系列」入门第十章:饼图绘制详解与实现

饼图绘制详解与实现 一、饼图绘制核心知识1. d3.arc() 弧形生成器2. d3.pie() 布局函数3. arc.centroid() 中心点计算4. 颜色方案 二、饼图实现代码小结核心知识点下章预告:力导向图 一、饼图绘制核心知识 1. d3.arc() 弧形生成器 功能: 生成圆形、扇形…...

三维点拟合平面ransac c++

理论 平面的一般定义 在三维空间中,一个平面可以由两个要素唯一确定: 法向量 n(a,b,c):垂直于平面的方向 平面上一点 平面上任意一点 p(x,y,z) 满足: ( p − p 0 ) ∗ n 0 (p - p0) * n 0 (p−p0)∗n0 即 a ( x − x 0 ) …...

第六章:6.6输入以下的杨辉三角形,要求输出10行

//输入以下的杨辉三角形&#xff0c;要求输出10行 #include<stdio.h> int main() {int a[10][10] { 0 };int i 0, j 0;for (i 0; i < 10; i){for (j 0; j < 10; j){if (j 0){a[i][j] 1;}else if (i j){a[i][j] 1;}else{a[i][j] a[i - 1][j - 1] a[i - …...

初识Redis · C++客户端string

目录 前言&#xff1a; string的API使用 set get&#xff1a; expire: NX XX: mset,mget&#xff1a; getrange setrange: incr decr 前言&#xff1a; 在前文&#xff0c;我们已经学习了Redis的定制化客户端怎么来的&#xff0c;以及如何配置好Redis定制化客户端&…...

React 事件处理基础

React 中最常见的两个需求&#xff0c;一个是列表渲染&#xff0c;另一个就是绑定点击事件。 这一篇就是从最基础的按钮点击开始&#xff0c;分四个阶段&#xff0c;逐步理解 React 中事件的写法和参数传递方式。 &#x1f4cd;阶段一&#xff1a;最简单的点击事件 function A…...

插入排序和希尔排序

今天给小伙伴们分享两个比较基础的排序算法&#xff0c;插入排序和希尔排序&#xff0c;这两个排序算法之间联系还是挺多的&#xff0c;所以放在一起。希尔排序可以看作是插入排序的升级版&#xff0c;在面对一些更为复杂的场景时&#xff0c;希尔排序的效率往往要比插入排序高…...

Model Context Protocol (MCP) 开放协议对医疗多模态数据整合的分析路径【附代码】

Model Context Protocol (MCP) 作为一种革命性的开放协议,正在重塑医疗领域多模态数据整合的方式。本文将深入分析MCP协议在医疗多模态数据整合中的具体路径、技术实现、应用场景及未来发展方向,揭示这一协议如何成为连接AI与医疗数据的关键桥梁。 MCP协议概述及其在医疗多模…...

Oracle 11g通过dg4odbc配置dblink连接PostgreSQL

1、安装unixodbc 2、安装postgresql yum install -y postgresql17-odbc 3、配置postgresqlodbc数据源 vim /usr/local/etc/odbcinst.ini##添加如下 [mypg] Driver /usr/lib64/psqlodbcw.so Servername localhost Port 5432 Database postgres Username postgres Pas…...

docker 安装prometheus普罗米修斯

prometheus&#xff08;普罗米修斯&#xff09;&#xff1a;天生为采集存储监控数据而生的时序数据库。prometheus通过各种Exporter采集到监控数据&#xff0c;然后存储进prometheus中&#xff0c;以供查询展示 grafana&#xff1a;一个监控仪表系统。grafana的数据来源可以有…...

Ubuntu上安装Mysql

步骤 1&#xff1a;安装 MySQL Server sudo apt update sudo apt install mysql-server -y这将安装最新版本的 MySQL 8.0 以及所有依赖组件。 步骤 2&#xff1a;检查安装是否成功 mysql --version sudo systemctl status mysql如果状态是 active (running)&#xff0c;说明成…...

Spring Boot启动流程深度解析:从main()到应用就绪的完整旅程

&#x1f331; Spring Boot启动流程深度解析&#xff1a;从main()到应用就绪的完整旅程 #SpringBoot核心 #启动原理 #自动配置 #源码解析 一、启动流程图解 (1) 启动类执行 → (2) SpringApplication初始化 → (3) 事件驱动模型启动 ↓ …...

2025TGCTF Web WP复现

AAA 偷渡阴平 <?php$tgctf2025$_GET[tgctf2025];if(!preg_match("/0|1|[3-9]|\~|\|\|\#|\\$|\%|\^|\&|\*|\&#xff08;|\&#xff09;|\-|\|\|\{|\[|\]|\}|\:|\|\"|\,|\<|\.|\>|\/|\?|\\\\/i", $tgctf2025)){//hint&#xff1a;你可以对着键盘…...

交叉注意力层的实质作用:连接编码器和解码器

交叉注意力层的实质作用 在Transformer架构里,交叉注意力层主要作用是连接编码器和解码器,让解码器能够利用编码器输出的上下文信息 。具体来说: 聚焦相关信息:以机器翻译任务为例,在将源语言句子翻译成目标语言时,交叉注意力能使解码器生成的每个词,都聚焦于源语言序列…...

conversation_template | conversation_actors | conversation_line_template

目录 conversation_template conversation_actors conversation_line_template 实例应用 conversation_template id&#xff1a;某段谈话的唯一编号FirstLineId&#xff1a;谈话开始的第一段话的编号&#xff0c;取值来源 ConversationLine.db2 的 ID 字段TextureKitId&am…...

C++ `shared_ptr` 多线程使用

C shared_ptr 多线程使用 一、核心结论 引用计数&#xff1a;shared_ptr 的引用计数操作是原子的&#xff0c;线程安全控制块修改&#xff1a;修改 shared_ptr 指向的对象需要同步被管理对象&#xff1a;若对象本身非线程安全&#xff0c;访问时仍需加锁 二、分场景详解 场景…...

十天借助 Trae 实现 “幸运塔塔屋” 小程序时光记忆功能之旅

在软件开发的广阔天地中&#xff0c;创新与效率始终是开发者们不懈追求的目标。近期&#xff0c;我成功完成了一次极具挑战性与创新性的实践 —— 仅用十天时间&#xff0c;借助 Trae 这款强大的 AI 工具&#xff0c;开发出了 “幸运塔塔屋” 小程序&#xff0c;其中的 “时光记…...

WiFi“管家”------hostapd的工作流程

目录 1. 启动与初始化 1.1 解析命令行参数 1.2 读取配置文件 1.3 创建接口和 BSS 数据结构 1.4 初始化驱动程序 2. 认证和关联处理 2.1 监听认证请求 2.2 处理认证请求 2.3 处理关联请求 3. 数据转发 3.1 接收客户端数据 3.2 转发数据 4. 断开连接处理 4.1 处理客…...

计算机视觉——基于使用 OpenCV 与 Python 实现相机标定畸变校正

概述 相机标定是一种旨在通过确定相机的内参&#xff08;焦距、光学中心、畸变系数&#xff09;和外参&#xff08;相机的位置和方向&#xff09;&#xff0c;提高图像在现实世界中的几何精度的过程。该过程可以纠正相机拍摄的图像中的畸变&#xff0c;使相机能够准确感知现实…...

OOM 未触发 JVM 崩溃的可能原因

1. OOM 未触发 JVM 崩溃的可能原因‌ (1) 未配置 JVM 参数强制崩溃‌ 关键参数缺失‌&#xff1a; 若未添加 -XX:CrashOnOutOfMemoryError&#xff0c;JVM 在 OOM 时可能仅抛出异常并正常退出&#xff0c;而非崩溃&#xff0c;因此不会生成 hs_err_pid.log。 # 正确配置示例&…...

计算机视觉cv2入门之车牌号码识别

前边我们已经讲解了使用cv2进行图像预处理与边缘检测等方面的知识&#xff0c;这里我们以车牌号码识别这一案例来实操一下。 大致思路 车牌号码识别的大致流程可以分为这三步&#xff1a;图像预处理-寻找车牌轮廓-车牌OCR识别 接下来我们按照这三步来进行讲解。 图像预处理 …...

xml+html 概述

1.什么是xml xml 是可扩展标记语言的缩写&#xff1a; Extensible Markup Language。 <root><h1> text 1</h1> </root> web 应用开发&#xff0c;需要配置 web.xml&#xff0c;就是个典型的 xml文件 <web-app><servlet><servlet-name&…...

C++数据结构与二叉树详解

前言&#xff1a; 在C编程的世界里&#xff0c;数据结构是构建高效程序的基石&#xff0c;而二叉树则是其中最优雅且应用广泛的数据结构之一。本文将带你深入理解二叉树的本质、实现与应用&#xff0c;助你在算法设计中游刃有余。 一、二叉树的基本概念 1. 什么是二叉树 二叉树…...

解决6栈6层码头集装箱堆栈翻箱最优解问题

‘’’ con 1 origin_stack = [ [4, 4, 1, 0, 0, 0], # 第一栈 [4, 3, 2, 1, 0, 0], # 第二栈 [4, 2, 2, 1, 0, 0], # 第三栈 [3, 3, 3, 1, 0, 0], # 第四栈 [3, 4, 2, 1, 0, 0], # 第五栈 [4, 2, 3, 2, 0, 0] # 第六栈 ] con 2 origin_stack = [ [4, 4, 3, 0, 0, 0], # 第一栈…...

Java 序列化与反序列化终极解析

Java 序列化与反序列化终极解析 1. 核心概念 (1) 什么是序列化&#xff1f; 定义&#xff1a;将对象转换为字节流的过程&#xff08;对象 → 字节&#xff09; 目的&#xff1a; 持久化存储&#xff08;如保存到文件&#xff09; 网络传输&#xff08;如RPC调用&#xff09…...

YOLOv5、YOLOv6、YOLOv7、YOLOv8、YOLOv9、YOLOv10、YOLOv11、YOLOv12的网络结构图

文章目录 一、YOLOv5二、YOLOv6三、YOLOv7四、YOLOv8五、YOLOv9六、YOLOv10七、YOLOv11八、YOLOv12九、目标检测系列文章 本文将给出YOLO各版本&#xff08;YOLOv5、YOLOv6、YOLOv7、YOLOv8、YOLOv9、YOLOv10、YOLOv11、YOLOv12&#xff09;网络结构图的绘制方法及图。本文所展…...

leetcode0145. 二叉树的后序遍历-easy

1 题目&#xff1a;二叉树的后序遍历 官方标定难度&#xff1a;易 给你一棵二叉树的根节点 root &#xff0c;返回其节点值的 后序遍历 。 示例 1&#xff1a; 输入&#xff1a;root [1,null,2,3] 输出&#xff1a;[3,2,1] 解释&#xff1a; 示例 2&#xff1a; 输入…...

【Leetcode 每日一题】2364. 统计坏数对的数目

问题背景 给你一个下标从 0 0 0 开始的整数数组 n u m s nums nums。如果 i < j i < j i<j 且 j − i ≠ n u m s [ j ] − n u m s [ i ] j - i \ne nums[j] - nums[i] j−inums[j]−nums[i]&#xff0c;那么我们称 ( i , j ) (i, j) (i,j) 是一个 坏数对 。…...

完整的 .NET 6 分布式定时任务实现(Hangfire + Redis 分布式锁)

完整的 .NET 6 分布式定时任务实现&#xff08;Hangfire Redis 分布式锁&#xff09; 以下是完整的解决方案&#xff0c;包含所有必要组件&#xff1a; 1. 基础设施层 1.1 分布式锁服务 // IDistributedLockService.cs public interface IDistributedLockService {ValueTa…...

人脸识别联合行为检测的办公管理新模式

基于人脸识别与行为检测的办公智能化解决方案 一、背景 在传统办公场景中&#xff0c;员工考勤管理、工位使用情况统计、安全监控等环节存在诸多痛点。例如&#xff0c;传统考勤方式如指纹打卡、刷卡等存在代打卡现象&#xff0c;考勤数据不准确&#xff1b;对于员工是否在工…...

鸿蒙NEXT开发键盘工具类(ArkTs)

export declare type KeyboardCallBack (show: boolean, height: number) > void; import { AppUtil } from ./AppUtil; import { LogUtil } from ./LogUtil; import { ArrayUtil } from ./ArrayUtil;/*** 键盘工具类* author 鸿蒙布道师* since 2025/04/18*/ export class…...

Python爬虫第17节-动态渲染页面抓取之Selenium使用下篇

目录 引言 一、获取节点信息 1.1 获取属性 1.2 获取文本值 1.3 获取ID、位置、标签名、大小 二、切换Frame 三、延时等待 3.1 隐式等待 3.2 显式等待 四、前进后退 五、Cookies 六、选项卡管理 七、异常处理 引言 这一节我们继续讲解Selenium的使用下篇&#xff0…...

【数据结构】第四弹——LinkedList与链表

文章目录 一. ArrayList 的缺陷二.链表2.1 链表的概念及结构2.2 链表的结构2.2.1 单向或者双向2.2.2 带头或者不带头2.2.3 循环非循环 2.3 链表的实现1. IList接口2. MySingleList 类中具体实现(不带头单向非循环链表)1. 节点抽象成内部类手搓一个链表2. 头插法3. 尾插法4. 指定…...

设计模式从入门到精通之(五)观察者模式

观察者模式&#xff1a;实现高效事件通知的秘诀 在日常生活中&#xff0c;我们经常需要同步通知多方的信息变更。比如天气预报系统、股票价格波动提醒、社交媒体的点赞通知等。这些场景中&#xff0c;通知机制需要高效、灵活&#xff0c;而不会因为通知方的变化影响系统整体。 …...