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

《Spring Framework实战》9:4.1.4.依赖注入

欢迎观看《Spring Framework实战》视频教程

典型的企业应用程序不是由单个对象(或Spring术语中的bean)组成。即使是最简单的应用程序也有几个对象协同工作,以呈现最终用户所认为的连贯应用程序。下一节将解释如何从定义多个独立的bean定义到一个完全实现的应用程序,在这个应用程序中,对象协作以实现目标。

本部分摘要

  1. 依赖注入
  2. 依赖项和配置详细信息
  3. 使用 depends-on
  4. 延迟初始化的 Bean
  5. 自动装配协作者
  6. 方法注入
        1. 依赖注入

依赖注入(Dependency injection)(DI)是一种过程,对象仅通过构造函数参数、工厂方法的参数或在对象实例构造或从工厂方法返回后在对象实例上设置的属性来定义其依赖关系(即它们所使用的其他对象)。然后,容器在创建bean时注入这些依赖项。这个过程从根本上说是bean本身的逆过程(因此称为控制反转),bean通过使用类的直接构造或服务定位器模式来控制其依赖关系的实例化或位置。

DI原则使代码更清晰,当对象提供了它们的依赖关系时,解耦更有效。对象不查找其依赖关系,也不知道依赖关系的位置或类。因此,你的类变得更容易测试,特别是当依赖关系是在接口或抽象基类上时,这允许在单元测试中使用存根或模拟实现。

DI存在两种主要变体:基于构造函数的依赖注入基于设置器的依赖注入

          1. 基于构造函数的依赖注入

基于构造的依赖注入是由调用具有大量参数的构造函数的容器完成的,每个参数代表一个从属关系。要求static 工厂方法与特定的参数构造的Bean几乎是等价的,这个讨论将参数处理为构造函数和static 类似的工厂方法。下面的例子显示了一类只能依赖于结构注入的类:

Java

public class SimpleMovieLister {

// the SimpleMovieLister has a dependency on a MovieFinder

private final MovieFinder movieFinder;

// a constructor so that the Spring container can inject a MovieFinder

public SimpleMovieLister(MovieFinder movieFinder) {

this.movieFinder = movieFinder;

}

// business logic that actually uses the injected MovieFinder is omitted...

}

注意,这个类没有什么特别的。它是一个POJO,它不依赖于容器特定的接口、基类或注释。

            1. 构造函数参数解析

使用参数的类型进行构造参数解析匹配。如果在一个Bean定义的构造函数参数中存在正态歧义,那么在一个Bean定义中定义构造函数参数的顺序是,当这些参数被实例化时,这些参数将被提供给适当的构造函数。考虑下列类别:

Java

package x.y;

public class ThingOne {

public ThingOne(ThingTwo thingTwo, ThingThree thingThree) {

// ...

}

}

假设ThingTwo和ThingThree类没有继承关系,则不存在潜在的歧义。因此,以下配置工作正常,您不需要在<constructor arg/>元素中显式指定构造函数参数索引或类型。

<beans>

<bean id="beanOne" class="x.y.ThingOne">

<constructor-arg ref="beanTwo"/>

<constructor-arg ref="beanThree"/>

</bean>

<bean id="beanTwo" class="x.y.ThingTwo"/>

<bean id="beanThree" class="x.y.ThingThree"/>

</beans>

当引用另一个bean时,类型是已知的,可以进行匹配(就像前面的例子一样)。当使用简单类型时,例如<value>true</value>,Spring无法确定值的类型,因此在没有帮助的情况下无法按类型匹配。考虑以下类:

Java

package examples;

public class ExampleBean {

// Number of years to calculate the Ultimate Answer

private final int years;

// The Answer to Life, the Universe, and Everything

private final String ultimateAnswer;

public ExampleBean(int years, String ultimateAnswer) {

this.years = years;

this.ultimateAnswer = ultimateAnswer;

}

}

            1. 构造函数参数类型匹配

在前面的场景中,如果您通过type属性显式指定构造函数参数的类型,则容器可以使用简单类型的类型匹配,如下例所示:

<bean id="exampleBean" class="examples.ExampleBean">

<constructor-arg type="int" value="7500000"/>

<constructor-arg type="java.lang.String" value="42"/>

</bean>

            1. 构造者参数索引

您可以使用index属性显式指定构造函数参数的索引,如下例所示:

<bean id="exampleBean" class="examples.ExampleBean">

<constructor-arg index="0" value="7500000"/>

<constructor-arg index="1" value="42"/>

</bean>

除了解决多个简单值的歧义外,指定索引还可以解决构造函数有两个相同类型参数的歧义。

该指数以0为基础。

            1. 构造者参数名称

您还可以使用构造函数参数名称进行值消歧,如下例所示:

<bean id="exampleBean" class="examples.ExampleBean">

<constructor-arg name="years" value="7500000"/>

<constructor-arg name="ultimateAnswer" value="42"/>

</bean>

请记住,为了开箱即用,您的代码必须在启用了-parameters标志的情况下编译,以便Spring可以从构造函数中查找参数名称。如果您不能或不想使用-parameters标志编译代码,可以使用@ConstructorProperties JDK注释显式命名构造函数参数。然后,示例类必须如下所示:

Java

package examples;

public class ExampleBean {

// Fields omitted

@ConstructorProperties({"years", "ultimateAnswer"})

public ExampleBean(int years, String ultimateAnswer) {

this.years = years;

this.ultimateAnswer = ultimateAnswer;

}

}

          1. 基于设置的依赖注入

基于Setter的DI是通过容器在调用无参数构造函数或无参数静态工厂方法实例化bean后调用bean上的Setter方法来实现的。

以下示例显示了一个只能通过使用纯setter注入进行依赖注入的类。这个类是传统的Java。它是一个POJO,不依赖于容器特定的接口、基类或注释。

Java

public class SimpleMovieLister {

// the SimpleMovieLister has a dependency on the MovieFinder

private MovieFinder movieFinder;

// a setter method so that the Spring container can inject a MovieFinder

public void setMovieFinder(MovieFinder movieFinder) {

this.movieFinder = movieFinder;

}

// business logic that actually uses the injected MovieFinder is omitted...

}

ApplicationContext为其管理的bean支持基于构造函数基于设置器的DI。在通过构造函数方法注入了一些依赖关系后,它还支持基于setter的DI。您可以以BeanDefinition的形式配置依赖关系,并将其与PropertyEditor实例结合使用,以将属性从一种格式转换为另一种格式。然而,大多数Spring用户并不直接使用这些类(即以编程方式),而是使用XML bean定义、带注释的组件(即用@Component、@Controller等注释的类)或基于Java的@Configuration类中的@bean方法。然后,这些源在内部转换为BeanDefinition的实例,并用于加载整个Spring IoC容器实例。

基于构造函数还是基于设置器的DI?

由于可以混合使用基于构造函数和基于设置器的DI,因此将构造函数用于强制依赖关系,将设置器方法或配置方法用于可选依赖关系是一个很好的经验法则。请注意,在setter方法上使用@Autowired注释可以使属性成为必需的依赖项;然而,构造函数注入和参数的编程验证是可取的。

Spring团队通常提倡构造函数注入,因为它允许您将应用程序组件实现为不可变对象,并确保所需的依赖关系不为空。此外,构造函数注入的组件总是以完全初始化的状态返回给客户端(调用)代码。顺便说一句,大量的构造函数参数是一种难闻的代码气味,这意味着该类可能有太多的职责,应该重构以更好地解决适当的关注点分离问题。

Setter注入应该主要用于可选依赖项,这些依赖项可以在类中分配合理的默认值。否则,必须在代码使用依赖关系的任何地方执行非空检查。setter注入的一个好处是,setter方法使该类的对象易于重新配置或稍后重新注入。因此,通过JMX MBean进行管理是setter注入的一个引人注目的用例。

使用对特定类最有意义的DI样式。有时,在处理您没有源代码的第三方类时,会为您做出选择。例如,如果第三方类不公开任何setter方法,那么构造函数注入可能是DI的唯一可用形式。

          1. 依赖解过程

容器执行bean依赖解析,如下所示:

  1. ApplicationContext是使用描述所有bean的配置元数据创建和初始化的。配置元数据可以通过XML、Java代码或注释指定。
  2. 对于每个bean,它的依赖关系都以属性、构造函数参数或静态工厂方法的参数的形式表示(如果你使用它而不是普通的构造函数)。这些依赖关系在bean实际创建时提供给bean。
  3. 每个属性或构造函数参数都是要设置的值的实际定义,或者是对容器中另一个bean的引用。
  4. 作为值的每个属性或构造函数参数都会从其指定格式转换为该属性或构造函数的实际类型。默认情况下,Spring可以将以字符串格式提供的值转换为所有内置类型,如int、long、string、boolean等。

Spring容器在创建容器时验证每个bean的配置。但是,在实际创建bean之前,bean属性本身不会被设置。创建容器时,会创建单例作用域并设置为预实例化(默认)的Bean。作用域在Bean作用域中定义。否则,bean仅在被请求时创建。创建bean可能会导致创建bean图,因为bean的依赖关系及其依赖关系(等等)被创建和分配。请注意,这些依赖关系之间的解析不匹配可能会在稍后出现,即在首次创建受影响的bean时出现。

循环依赖关系

如果您主要使用构造函数注入,则可能会创建无法解决的循环依赖场景。

例如:类A通过构造函数注入需要类B的实例,类B通过构造函数注入要求类A的实例。如果将bean配置为类A和B相互注入,Spring IoC容器将在运行时检测到此循环引用,并抛出BeanCurrentlyCreationException。

一种可能的解决方案是编辑一些类的源代码,由setter而不是构造函数配置。或者,避免构造函数注入,只使用setter注入。换句话说,虽然不建议这样做,但您可以使用setter注入配置循环依赖关系。

与典型的情况(没有循环依赖)不同,bean a和bean B之间的循环依赖迫使其中一个bean在完全初始化之前注入另一个bean(经典的鸡和蛋场景)。

一般来说,你可以相信Spring会做正确的事情。它在容器加载时检测配置问题,例如对不存在的bean的引用和循环依赖关系。Spring在bean实际创建时尽可能晚地设置属性并解析依赖关系。这意味着,如果创建对象或其依赖项时出现问题,正确加载的Spring容器可以在以后请求对象时生成异常——例如,bean因缺少或无效属性而抛出异常。一些配置问题的可见性可能会延迟,这就是ApplicationContext实现默认预实例化单例bean的原因。在实际需要之前创建这些bean需要一些前期时间和内存,但在创建ApplicationContext时,而不是以后,您会发现配置问题。您仍然可以覆盖此默认行为,以便单例bean延迟初始化,而不是急切地预实例化。

如果不存在循环依赖关系,当一个或多个协作bean被注入依赖bean时,每个协作bean在注入依赖bean之前都会被完全配置。这意味着,如果bean A依赖于bean B,Spring IoC容器会在调用bean A的setter方法之前完全配置bean B。换句话说,bean被实例化(如果它不是预实例化的单例),其依赖关系被设置,相关的生命周期方法(如配置的init方法或InitializingBean回调方法)被调用。

          1. 依赖注入的例子

下面的示例使用基于xml的配置元数据为基于环境的di。一个SpringXML配置文件的一小部分指定了如下的一些Bean定义:

<bean id="exampleBean" class="examples.ExampleBean">

<!-- setter injection using the nested ref element -->

<property name="beanOne">

<ref bean="anotherExampleBean"/>

</property>

<!-- setter injection using the neater ref attribute -->

<property name="beanTwo" ref="yetAnotherBean"/>

<property name="integerProperty" value="1"/>

</bean>

<bean id="anotherExampleBean" class="examples.AnotherBean"/>

<bean id="yetAnotherBean" class="examples.YetAnotherBean"/>

下面的示例显示相应的ExampleBean 班级:

Java

public class ExampleBean {

private AnotherBean beanOne;

private YetAnotherBean beanTwo;

private int i;

public void setBeanOne(AnotherBean beanOne) {

this.beanOne = beanOne;

}

public void setBeanTwo(YetAnotherBean beanTwo) {

this.beanTwo = beanTwo;

}

public void setIntegerProperty(int i) {

this.i = i;

}

}

在前面的示例中,设置者声明与XML文件中指定的属性匹配。下面的例子是使用基于建筑的数据交换:

<bean id="exampleBean" class="examples.ExampleBean">

<!-- constructor injection using the nested ref element -->

<constructor-arg>

<ref bean="anotherExampleBean"/>

</constructor-arg>

<!-- constructor injection using the neater ref attribute -->

<constructor-arg ref="yetAnotherBean"/>

<constructor-arg type="int" value="1"/>

</bean>

<bean id="anotherExampleBean" class="examples.AnotherBean"/>

<bean id="yetAnotherBean" class="examples.YetAnotherBean"/>

下面的示例显示相应的ExampleBean 班级:

Java

public class ExampleBean {

private AnotherBean beanOne;

private YetAnotherBean beanTwo;

private int i;

public ExampleBean(

AnotherBean anotherBean, YetAnotherBean yetAnotherBean, int i) {

this.beanOne = anotherBean;

this.beanTwo = yetAnotherBean;

this.i = i;

}

}

在Bean定义中指定的构造函数参数被用作构造函数的参数。ExampleBean .

现在考虑这个例子的一个变体,在这里,使用的不是构造函数,而是Spring调用一个static 返回对象实例的工厂方法:

<bean id="exampleBean" class="examples.ExampleBean" factory-method="createInstance">

<constructor-arg ref="anotherExampleBean"/>

<constructor-arg ref="yetAnotherBean"/>

<constructor-arg value="1"/>

</bean>

<bean id="anotherExampleBean" class="examples.AnotherBean"/>

<bean id="yetAnotherBean" class="examples.YetAnotherBean"/>

下面的示例显示相应的ExampleBean 班级:

Java

public class ExampleBean {

// a private constructor

private ExampleBean(...) {

...

}

// a static factory method; the arguments to this method can be

// considered the dependencies of the bean that is returned,

// regardless of how those arguments are actually used.

public static ExampleBean createInstance (

AnotherBean anotherBean, YetAnotherBean yetAnotherBean, int i) {

ExampleBean eb = new ExampleBean (...);

// some other operations...

return eb;

}

}

辩论static 工厂方法由<constructor-arg/> 元素,和构造函数实际上被使用的完全一样。由工厂方法返回的类的类型不必与包含static 工厂方法(尽管在本例中是)。实例(非静态)工厂法可以使用基本相同的方式使用。factory-bean 代替了class 所以我们在这里不讨论这些细节。

相关文章:

《Spring Framework实战》9:4.1.4.依赖注入

欢迎观看《Spring Framework实战》视频教程 典型的企业应用程序不是由单个对象&#xff08;或Spring术语中的bean&#xff09;组成。即使是最简单的应用程序也有几个对象协同工作&#xff0c;以呈现最终用户所认为的连贯应用程序。下一节将解释如何从定义多个独立的bean定义到一…...

linux之自动挂载

如果想要实现自动挂载&#xff0c;应该挂在客户端&#xff01;&#xff01;&#xff01;&#xff01;&#xff01; 客户端&#xff1a; [rootlocalhost ~]# yum install nfs-utils -y &#xff08;下载软件&#xff09; [rootlocalhost ~]# systemctl start nfs-utils.servic…...

python+fpdf:创建pdf并实现表格数据写入

目录 创建pdf文件对象 新增页 添加自定义字体 设置字体 设置文字颜色和背景色 插入内容 换行 插入图片 保存pdf 完整代码 安装:pip install fpdf 创建pdf文件对象 from fpdf import FPDF, Alignpdf = FPDF() # 创建pdf文件对象 获取边距 print(pdf.l_margin, p…...

比较procfs 、 sysctl和Netlink

procfs 文件系统和 sysctl 的使用: procfs 文件系统(/proc) procfs 文件系统是 Linux 内核向用户空间暴露内核数据结构以及配置信息的一种方式。`procfs` 的挂载点是 /proc 目录,这个目录中的文件和目录呈现内核的运行状况和配置信息。通过读写这些文件,可以查看和控制内…...

第四、五章补充:线代本质合集(B站:小崔说数)

视频1&#xff1a;线性空间 原视频&#xff1a;【线性代数的本质】向量空间、基向量的几何解释_哔哩哔哩_bilibili 很多同学在学习线性代数的时候&#xff0c;会遇到一个困扰&#xff0c;就是不知道什么是线性空间。因为中文的教材往往对线性空间的定义是非常偏数学的&#x…...

Clojure语言的函数实现

Clojure语言函数实现详解 引言 Clojure是一种基于Java虚拟机的函数式编程语言&#xff0c;以其简洁和强大的数据处理能力而著称。在Clojure中&#xff0c;函数是基本的构造块&#xff0c;良好的函数设计可以提高代码的可复用性和可维护性。本文将深入探讨Clojure中的函数实现…...

Windows10环境下安装RabbitMq折腾记

最近有个老项目需要迁移到windows10环境&#xff0c;用的是比较老的rabbitmq安装包&#xff0c;如下所示。经过一番折腾&#xff0c;死活服务起不来&#xff0c;最终果断放弃老版本启用新版本。现在把折腾过程记录下&#xff1a; 一、安装erlang 安装完成后的目录结构&#xff…...

【前端,TypeScript】TypeScript速成(九):async-await 语法糖

async-await 语法糖 可以使用 async-await 来管理 Promise&#xff0c;下例重写上一节使用 Promise then 的形式计算 ( 2 3 ) ( 4 5 ) (23) \times (45) (23)(45)&#xff1a; function add(a: number, b: number): Promise<number>{return new Promise((resolve,…...

基于ADAS 与关键点特征金字塔网络融合的3D LiDAR目标检测原理与算法实现

一、概述 3D LiDAR目标检测是一种在三维空间中识别和定位感兴趣目标的技术。在自动驾驶系统和先进的空间分析中&#xff0c;目标检测方法的不断演进至关重要。3D LiDAR目标检测作为一种变革性的技术&#xff0c;在环境感知方面提供了前所未有的准确性和深度信息. 在这里&…...

STM32供电参考设计

STM32供电参考设计 ​ 在图中有VDD&#xff0c;VSS和VDDA&#xff0c;VSSA两种类型的供电引脚&#xff0c;其数据手册解释如下&#xff1a; ​ 令我不解的是&#xff1a;VDDA和VSSA必须分别连接到VDD和VSS&#xff0c;这是什么意思&#xff1f;有大佬能够解答一下吗&#xff1f…...

C/C++头文件uitility

在C中&#xff0c;<utility>头文件提供了一些通用的工具类和函数&#xff0c;这些工具类和函数在编写高效、可读性强的代码时非常有用。以下是<utility>头文件中一些常用函数和类的详细介绍及使用示例&#xff1a; std::pair&#xff1a;一个模板类&#xff0c;用于…...

Nature Electronics——近传感器计算:50 nm异构集成技术的革命

创新点&#xff1a;1.高密度互联设计&#xff1a;基于二维材料&#xff0c;开发出互连密度高达62,500 I/O每平方毫米的M3D集成结构。2.异构层堆叠&#xff1a;整合了第二层石墨烯化学传感器和第一层MoS₂记忆晶体管&#xff0c;实现功能互补。3.超短传感器与计算元件距离&#…...

腾讯云AI代码助手编程挑战赛-图片转换工具

作品简介&#xff1a; 解决了人们学习生活中的图片格式转换问题&#xff0c; 制作该脚本&#xff0c;省去了打开在线编辑器操作的时间&#xff0c; 免费为用户提供图片格式的转换的实用小工具 技术架构 python语言的tk库来完成的GUI页面设计&#xff0c; 引用PIL包转换图…...

英伟达Project Digits赋能医疗大模型:创新应用与未来展望

英伟达Project Digits赋能医疗大模型&#xff1a;创新应用与未来展望 一、引言 1.1 研究背景与意义 在当今数字化时代&#xff0c;医疗行业作为关乎国计民生的关键领域&#xff0c;正面临着前所未有的挑战与机遇。一方面&#xff0c;传统医疗模式在应对海量医疗数据的处理、复…...

查找路由器的管理后台ip【通用找IP】

需求&#xff1a; 刚刚搞了个【小米】路由器&#xff0c;我想进路由的管理后台&#xff0c;提示&#xff1a;安装xx的路由管家&#xff0c;我不想安装 但是无法找到这个管理后台。 而且我是用这个路由作为中继&#xff0c;那么这个路由的ip就会经常更换 尝试通过网上搜索引擎来…...

Nginx:Stream模块

什么是 Stream 模块? Stream 模块 是 Nginx 的一个核心模块,专为处理非 HTTP 协议的流量(TCP 和 UDP 流量)而设计。它可以用来负载均衡和代理 TCP 或 UDP 连接,适用于多种应用场景,如: 数据库集群(MySQL、PostgreSQL 等)邮件服务器(SMTP、IMAP、POP3)游戏服务器VoI…...

C++语言的并发编程

C语言的并发编程 引言 随着计算机技术的飞速发展&#xff0c;尤其是多核处理器的普及&#xff0c;如何高效地利用计算机资源成为了一个重要话题。在这个背景下&#xff0c;并发编程已经成为了一种必须掌握的技能。C作为一种强大的编程语言&#xff0c;也提供了丰富的工具和库…...

Boost.Asio 同步读写及客户端 - 服务器实现详解

Boost.Asio 同步读写及客户端 - 服务器实现详解 参考文献 Boost.Asio 官方文档学习资料来源: 参考网址 一、引言 Boost.Asio作为一个强大的跨平台网络编程库&#xff0c;为开发者提供了丰富的网络操作接口。在之前的学习中&#xff0c;我们已接触到其同步读写的API函数&…...

机器人技术:ModbusTCP转CCLINKIE网关应用

在当今自动化生产与智能制造领域&#xff0c;ModbusTCP转CC-LinkIE网关KJ-MTCPZ-CCIES的应用正日益成为提升生产效率、实现设备间高效通信的重要技术手段。这一转换技术不仅打破了不同通信协议间的壁垒&#xff0c;还为机器人产品的应用提供了更为广阔的舞台。ModbusTCP作为一种…...

CSS——24.实战技能网导航栏 hove状态

<!DOCTYPE html> <html><head><meta charset"UTF-8"><title>技能网导航hover状态</title><style type"text/css">nav{width: 1000px;height: 40px;background:#363636;margin: 100px auto;}nav div{width: 100p…...

计算机视觉目标检测-DETR网络

目录 摘要abstractDETR目标检测网络详解二分图匹配和损失函数 DETR总结总结 摘要 DETR&#xff08;DEtection TRansformer&#xff09;是由Facebook AI提出的一种基于Transformer架构的端到端目标检测方法。它通过将目标检测建模为集合预测问题&#xff0c;摒弃了锚框设计和非…...

【计算机网络】课程 实验五 静态路由配置

实验五 静态路由配置 一、实验目的 理解静态路由的工作原理&#xff0c;掌握如何配置静态路由。 二、实验分析与设计 【背景描述】 假设校园网分为 2 个区域&#xff0c;每个区域内使用 1 台路由器连接 2 个子网&#xff0c; 现要在路由器上 做适当配置&#xff0c;实现校…...

FPGA车牌识别

基于FPGA的车牌识别主要包含以下几个步骤&#xff1a;图像采集、颜色空间转换、边缘检测、形态学处理&#xff08;腐蚀和膨胀&#xff09;、特征值提取、模板匹配、结果显示。先用matlab对原理进行仿真&#xff0c;后用vivado和modelsim进行设计和仿真。 一、1.图像采集采用ov…...

最好用的图文识别OCR -- PaddleOCR(2) 提高推理效率(PPOCR模型转ONNX模型进行推理)

在实际推理过程中&#xff0c;使用 PaddleOCR 模型时效率较慢&#xff0c;经测试每张图片的检测与识别平均耗时超过 5 秒&#xff0c;这在需要大规模自动化处理的场景中无法满足需求。为此&#xff0c;我尝试将 PaddleOCR 模型转换为 ONNX 格式进行推理&#xff0c;以提升效率。…...

STM32-笔记39-SPI-W25Q128

一、什么是SPI&#xff1f; SPI是串行外设接口&#xff08;Serial Peripheral Interface&#xff09;的缩写&#xff0c;是一种高速的&#xff0c;全双工&#xff0c;同步的通信总线&#xff0c;并且 在芯片的管脚上只占用四根线&#xff0c;节约了芯片的管脚&#xff0c;同时为…...

反规范化带来的数据不一致问题的解决方案

在数据库设计中&#xff0c;规范化&#xff08;Normalization&#xff09;和反规范化&#xff08;Denormalization&#xff09;是两个相互对立但又不可或缺的概念。规范化旨在消除数据冗余&#xff0c;确保数据的一致性和准确性&#xff0c;但可能会降低查询效率。相反&#xf…...

依赖注入学习

1.介绍 依赖注入&#xff08;Dependency Injection, DI&#xff09;是一种软件设计模式&#xff0c;用于实现类与其依赖项之间的解耦。它的核心思想是&#xff0c;将类所依赖的对象通过外部注入的方式传递给它&#xff0c;而不是在类内部自行创建依赖对象。通过这种方式&#…...

ESP32-C3 AT WiFi AP 启 TCP Server 被动接收模式 + BLE 共存

TCP 被动接收模式&#xff0c;每次发的数据会先存到缓冲区&#xff0c;参见&#xff1a;ATCIPRECVTYPE 指令说明。 即每包数据不会实时报告 IPD 接收情况&#xff0c;如果需要查询缓冲区的数据&#xff0c;先用 ATCIPRECVLEN? 指令查询被动接收模式下套接字数据的长度 。获取…...

git tag

文章目录 1.简介2.格式3.选项4.示例参考文献 1.简介 同大多数 VCS 一样&#xff0c;Git 也可以对某一时间点的版本打上标签&#xff0c;用于版本的发布管理。 一个版本发布时&#xff0c;我们可以为当前版本打上类似于 v.1.0.1、v.1.0.2 这样的 Tag。一个 Tag 指向一个 Commi…...

rabbitmq的三个交换机及简单使用

提前说一下&#xff0c;创建队列&#xff0c;交换机&#xff0c;绑定交换机和队列都是在生产者。消费者只负责监听就行了&#xff0c;不用配其他的。 完成这个场景需要两个服务哦。 1直连交换机-生产者的代码。 在配置类中创建队列&#xff0c;交换机&#xff0c;绑定交换机…...

TCP 如何获取端口信息

注&#xff1a;本文为 “TCP 如何获取端口信息” 相关讨论摘录。 机翻&#xff0c;未校。 How TCP Gets Port Information TCP 如何获取端口信息 asked Nov 10, 2024 at 19:57 user15503745 API Call for Connection API 调用以建立连接 Before the app can send data d…...

HashMap和HashTable的区别

1、HashMap是线程不安全的&#xff0c;HashTable是线程安全的 HashMap&#xff1a;Fail-fast 机制。表示快速失败&#xff0c;在集合遍历过程中&#xff0c;一旦发现容器中的数据被修改了&#xff0c;会立刻抛出ConcurrentModificationException异常&#xff0c;从而导致遍历失…...

USB 传输技术 OTG(On-The-Go)极简理解

OTG 极简理解 OTG&#xff0c;全称为 On-The-Go&#xff0c;它是一种 USB 传输技术 OTG 的主要应用于不同的设备或移动设备间的联接&#xff0c;进行数据交换 OTG 允许在没有电脑作为中转站的情况下&#xff0c;实现设备间的数据传送以及不同设备间的互相连接 在手机中&…...

SpringBoot插件

SpringBoot的插件机制是其强大灵活性的重要体现&#xff0c;它允许开发人员将应用程序的不同功能模块打包为独立的插件&#xff0c;并可以动态地加载和卸载这些插件。以下是对SpringBoot插件机制的详细解析&#xff1a; 一、插件机制的概念 插件机制是一种软件开发方法&#…...

【开发环境搭建篇】Visual Studio 2022 安装和使用

本文收录于 《C编程入门》专栏&#xff0c;从零基础开始&#xff0c;介绍C编程入门相关的内容&#xff0c;欢迎关注&#xff0c;谢谢&#xff01; 文章目录 一、前言二、下载三、安装四、使用五、总结 一、前言 本文介绍如何在Windows环境下安装Visual Studio 2022。 什么是Vi…...

深度学习:Java DL4J基于RNN构建智能停车管理模型

### 深度学习&#xff1a;Java DL4J基于RNN构建智能停车管理模型 #### 引言 随着城市化进程的加速&#xff0c;停车问题日益成为城市管理的难点和痛点。传统的停车场管理方式效率低下&#xff0c;导致停车场资源无法得到充分利用&#xff0c;车主停车体验差。为了解决这些痛点…...

创建型模式-工厂模式

工厂模式是一种创建型的设计模式&#xff0c;原理是父类提供一个创建对象的方法&#xff0c;允许子类去实现具体的实例化对象。通过此模式可减少创建和具体的产品之间的耦合关系。 适用场景&#xff1a; 1、当需求中无法预估对象确切类别及个别的依赖关系。例如&#xff1a; …...

UI自动化测试框架playwright--初级入门

一、背景&#xff1a;UI自动化的痛点&#xff1a; 1、设计脚本耗时&#xff1a; 需要思考要如何模拟用户的操作&#xff0c;如何触发页面的事件&#xff0c;还要思考如何设计脚本&#xff0c;定位和操作要交互的元素、路径、位置&#xff0c;再编写代码逻辑&#xff0c;往复循…...

算法 -归并排序

博客主页&#xff1a;【夜泉_ly】 本文专栏&#xff1a;【算法】 欢迎点赞&#x1f44d;收藏⭐关注❤️ 文章目录 &#x1f500; 归并排序&#x1f4d6; 简介&#x1f5bc;️ 示意图&#x1f4a1; 实现思路&#x1f4bb; 代码实现&#x1f4a1; 实现思路2 - 非递归&#x1f4bb…...

基于html5实现音乐录音播放动画源码

源码介绍 基于html5实现音乐录音播放动画源码是一款类似Shazam的UI&#xff0c;点击按钮后&#xff0c;会变成为一个监听按钮。旁边会有音符飞入这个监听按钮&#xff0c;最后转换成一个音乐播放器。 效果预览 源码获取 基于html5实现音乐录音播放动画源码...

NRC优先级中比较特殊的—NRC0x13和NRC0x31

1、基础知识 大家都了解 NRC0x13&#xff0c;表示长度错误和格式错误 NRC0x31&#xff0c;表示DID不支持和数据格式不支持 2、为什么说这两个NRC比较特殊 看下图的标注部分&#xff1a; 2.1、先看NRC0x13 步骤一&#xff1a;仔细看是先判断Minmun Length Check &#xff0…...

文件的介绍4

一、文件的随机读写 1.fseek I 从左往右 第一个参数 stream 是一个 指向已经被打开的文件流 的指针 第三个参数 origin 是个常量&#xff0c;指定从哪个位置开始偏移&#xff0c;它的取值&#xff1a; SEEK_SET&#xff1a;从文件开头开始偏移。SEEK_CUR&#xff1a;从当前…...

Mysql - 多表连接和连接类型

在关系型数据库中&#xff0c;多表连接&#xff08;JOIN&#xff09;是用于从多个表中检索数据的常用操作。通过连接多个表&#xff0c;可以将分散在不同表中的相关数据组合在一起&#xff0c;从而进行更复杂的查询和分析。在这篇文章中&#xff0c;我们将深入探讨MySQL中的多表…...

Tableau数据可视化与仪表盘搭建-可视化原则及BI仪表盘搭建

目录 可视化原则 BI仪表盘搭建 仪表盘搭建原则 明确仪表盘主题 仪表盘主题拆解 开发设计工作表 经营情况总览&#xff1a;突出显示的文字 经营数据详情&#xff1a;表格 每日营收数据&#xff1a;多轴折线图 每日流量数据&#xff1a;双轴组合图 新老客占比&#xf…...

如何制作一份出色的公司介绍PPT?

制作一份公司介绍的PPT需要精心设计&#xff0c;以确保内容既专业又吸引人。以下是一个基本的框架和一些建议&#xff0c;帮助您创建一份有效的公司介绍PPT&#xff1a; PPT标题页 标题&#xff1a;公司全称&#xff08;可使用公司Logo作为背景或嵌入标题中&#xff09;副标题…...

【Arm】Arm 处理器的半主机(semihosting)机制

概览 通过 semihosting 机制&#xff0c;主机可以通过调试器使用目标计算机 IO 接口。 例如开发者的 PC 通过 J-Link 来使用 STM32 MCU 的输入输出。 这些功能的示例包括键盘输入、屏幕输出和硬盘 I/O。例如&#xff0c;可以使用此机制启用 C Library 中的函数&#xff0c;如…...

C语言基本知识复习浓缩版:输出函数printf

输出函数printf学习 printf()的作用是将文本输出到屏幕上使用之前需要先引入stdio.h头文件printf函数在使用的时候&#xff0c;至少需要一个参数 printf() 是 C 语言标准库中的一个函数&#xff0c;用于将格式化的文本输出到标准输出设备&#xff08;通常是屏幕&#xff09;。…...

pygame飞机大战

飞机大战 1.main类2.配置类3.游戏主类4.游戏资源类5.资源下载6.游戏效果 1.main类 启动游戏。 from MainWindow import MainWindow if __name__ __main__:appMainWindow()app.run()2.配置类 该类主要存放游戏的各种设置参数。 #窗口尺寸 #窗口尺寸 import random import p…...

WebRTC:构建实时通信应用的利器

都已无处不在。而 WebRTC&#xff08;Web Real-Time Communication&#xff09;则为开发者提供了一种简便的方式&#xff0c;来在浏览器中实现实时的音视频通信和数据传输。本文将介绍 WebRTC 的基本概念、工作原理&#xff0c;以及如何利用 WebRTC 构建实时通信应用。 什么是…...

个人博客搭建(二)—Typora+PicGo+OSS

个人博客站—运维鹿: http://www.kervin24.top CSDN博客—做个超努力的小奚&#xff1a; 做个超努力的小奚-CSDN博客 一、前言 博客搭建完一直没有更新&#xff0c;因为WordPress自带的文档编辑器不方便&#xff0c;以前用CSDN写作的时候&#xff0c;习惯了Typora。最近对比了…...