Spring IoCDI(2)—IoC详解

目录

一、IoC详解

1、Bean的存储

(1)@Controller(控制器存储)

获取bean对象的其他方式

Bean 命名约定

(2)@Service(服务存储)

(3)@Repository(仓库存储)

(4)@Component(组件存储)

(5)@Configuration(配置存储)

2、为什么要这么多类注解?

类注解之间的关系:

3、方法注解 @Bean

(1)方法注解要配合类注解使用

(2)定义多个对象

(3)重命名 Bean

4、扫描路径


一、IoC详解

        IoC控制反转就是将对象的控制权交给Spring的IoC容器,由IoC容器创建及管理对象也就是bean的存储

        共有两类注解类型可以实现:1、类注解:@Controller、@Service、@Repository、@Component、@Configuration2、方法注解:@Bean

1、Bean的存储

(1)@Controller(控制器存储)

        使用@Controller注解,存储bean的代码如下:

@Controller
public class UserController {
    public void sayHi() {
        System.out.println("hi, UserController");
    }
}

        这个对象加了@Controller注解,就把这个对象放在Spring容器中了,下面是从Spring容器获取对象,代码如下:

@SpringBootApplication
public class SpringIoC2Application {

    public static void main(String[] args) {
        //获取Spring的上下文
        ApplicationContext context = SpringApplication.run(SpringIoC2Application.class, args);
        //从Spring的上下文中获取对象
        UserController bean = (UserController)context.getBean(UserController.class);
        bean.sayHi();
    }
}

        ApplicantContent 翻译过来就是:Spring 上下文因为对象交给Spring管理了,所以获取对象要从Spring中获取,那么就得先得到Spring的上下文

        关于上下文的概念在计算机领域,上下文这个概念,在线程那已经了解过了,比如应用进行线程切换的时候,切换前都会把线程的状态信息暂时存储起来,这里的上下文就包括了当前线程的信息,等下次该线程又得到CPU时间的时候,从上下文中拿到线程上次运行的信息

        这里的上下文,就是当前的运行环境,也可以看做是一个容器,容器里存了很多内容,这些内容是当前运行的环境

        观察运行结果,发现成功从Spring中获取了Controller 对象,并执行Controller的sayHi方法,如图:

        如果把UserController类上面的注解@Controller去掉,就会报错,如图:

        报错信息找不到类型是com.example.springioc2.controller.UserController的bean因为没加这个注解,自然也就没声明把这个类交给Spring管理,Spring也就找不到该类的bean了

获取bean对象的其他方式

        上述代码是根据类型来查找对象的,如果Spring容器中,同一个类型存在多个bean的话,要怎么获取?ApplicationContext也提供了其他获取bean的方式,ApplicationContext获取bean对象的功能,是父类BeanFactory提供的功能。如下代码:

public interface BeanFactory {
    //以上省略...
    // 1. 根据bean名称获取bean
    Object getBean(String var1) throws BeansException;
    // 2. 根据bean名称和类型获取bean
    <T> T getBean(String var1, Class<T> var2) throws BeansException;
    // 3. 按bean名称和构造函数参数动态创建bean,只适⽤于具有原型(prototype)作⽤域的bean
    Object getBean(String var1, Object... var2) throws BeansException;
    // 4. 根据类型获取bean
    <T> T getBean(Class<T> var1) throws BeansException;
    // 5. 按bean类型和构造函数参数动态创建bean, 只适⽤于具有原型(prototype)作⽤域的bean
    <T> T getBean(Class<T> var1, Object... var2) throws BeansException;
    //以下省略...
}

        最常用的是1、2、4种,这三种方式(根据bean名称获取bean根据bean类型和名称获取bean根据bean类型获取bean),获取到的bean是一样的

        其中1、2种都涉及到根据名称来获取对象,那么bean的名称是什么呢?

Spring bean 是Spring框架在运行时管理的对象,Spring会给管理的对象起一个名字

比如学校管理学生,会给每个学生分配一个学号,根据学号,就可以找到对应的学生。

Spring也是如此,给每个对象都起一个名字,根据Bean的名称(BeanId)就可以获取到对应的对象

Bean 命名约定

官方文档:Bean Overview :: Spring Framework

        程序开发人员不需要为bean指定名称(BeanId),如果没有显示的提供名称(BeanId),Spring容器将为该bean生成唯一的名称。

        命名约定使用Java标准约定作为实例字段名。也就是bean名称以小写字母开头,然后使用驼峰式大小写。例子如下:

类名:UserController,Bean的名称为:userController

类名:AccountManager,Bean的名称为:accountManager

类名:AccountService,Bean的名称为:accountService

        也有一些特殊情况,当多个字符并且第一个字符和第二个字符都是大写时,将保留原始大小写。这些规则与java.beans.Introspector.decapitalize(Spring在这里使用的)定义的规则相同。例子如下:

类名:UController,Bean的名称为:UController

类名:AManager,Bean的名称为:AManager

        根据这个命名规则,我们来获取Bean,代码如下:

@SpringBootApplication
public class SpringIoC2Application {

    public static void main(String[] args) {
        //获取Spring的上下文
        ApplicationContext context = SpringApplication.run(SpringIoC2Application.class, args);
        //从Spring的上下文中获取对象
        //根据bean类型,从Spring上下文中获取对象
        UserController userController1 = (UserController)context.getBean(UserController.class);
        //根据bean名称,从Spring上下文获取对象
        UserController userController2 = (UserController)context.getBean("userController");
        //根据bean名称+类型,从Spring上下文获取对象
        UserController userController3 = (UserController) context.getBean("userController", UserController.class);

        System.out.println(userController1);
        System.out.println(userController2);
        System.out.println(userController3);
    }
}

        运行结果如下图:

        地址都是一样的,说明对象是同一个。

ApplicationContext 和 BeanFactory (常见面试题)

1、从继承关系和功能方面来说Spring容器有两个顶级的接口:BeanFactory 和 ApplicationContext。其中BeanFactory提供了基础的访问容器的能力,而 ApplicationContext 属于 BeanFactory 的子类,它除了继承 BeanFactory 的所有功能外,它还有自己独特的特性,还添加了对国际化支持、资源访问支持、以及事件传播等方面支持

2、从性能方面来说ApplicationContext是一次性加载并初始化所有Bean对象(提前加载),而 BeanFactory 是需要哪个对象了,才去加载那个对象(懒加载),因此更轻量

(2)@Service(服务存储)

        使用@Service存储bean的代码如下:

@Service
public class UserService {
    public void doService() {
        System.out.println("do Service...");
    }
}

        读取bean的代码:

@SpringBootApplication
public class SpringIoC2Application {
    public static void main(String[] args) {
        //获取Spring上下文对象
        ApplicationContext context = SpringApplication.run(SpringIoC2Application.class, args);
        //从Spring中获取UserService对象
        UserService userService = context.getBean(UserService.class);
        //使用对象
        userService.doService();
    }
}

        执行结果如下:

        

        把注解@Service删掉,会报错,如图:

        和去掉@Controller注解一样的报错原因一样,找不到bean。

(3)@Repository(仓库存储)

        使用@Repository存储bean代码如下:

@Repository
public class UserRepository {
    public void doRepository() {
        System.out.println("do Repository...");
    }
}

        读取bean的代码:

@SpringBootApplication
public class SpringIoC2Application {
    public static void main(String[] args) {
        //获取Spring上下文对象
        ApplicationContext context = SpringApplication.run(SpringIoC2Application.class, args);
        //从Spring中获取UserRepository对象
        UserRepository userRepository = context.getBean(UserRepository.class);
        //使用对象
        userRepository.doRepository();
    }
}

        运行结果:

        同样把注解@Repository去掉,会报错,如图:

        原因和上面的一样。

(4)@Component(组件存储)

        使用@Component存储bean的代码:

@Component
public class UserComponent {
    public void doComponent() {
        System.out.println("do Component...");
    }
}

        读取bean的代码:

@SpringBootApplication
public class SpringIoC2Application {
    public static void main(String[] args) {
        //获取Spring上下文对象
        ApplicationContext context = SpringApplication.run(SpringIoC2Application.class, args);
        //从Spring中获取UserComponent对象
        UserComponent userComponent = context.getBean(UserComponent.class);
        //使用对象
        userComponent.doComponent();
    }
}

        执行结果:

        如果把注释@Component去掉,报错和上面的一样,如图:

(5)@Configuration(配置存储)

        使用@Configuration存储bean的代码如下:

@Configuration
public class UserConfiguration {
    public void doConfiguration() {
        System.out.println("do Configuration...");
    }
}

        读取bean的代码:

@SpringBootApplication
public class SpringIoC2Application {
    public static void main(String[] args) {
        //获取Spring上下文对象
        ApplicationContext context = SpringApplication.run(SpringIoC2Application.class, args);
        //从Spring中获取UserComponent对象
        UserConfiguration userConfiguration = context.getBean(UserConfiguration.class);
        //使用对象
        userConfiguration.doConfiguration();
    }
}

        执行结果如下:

        同样,把注释@Configuration去掉,会报错,原因和上面的都一样,结果如下:

2、为什么要这么多类注解?

        这个和前面的应用分层是对应的,程序员看到这些类注解后,就能直接了解当前类的用途。

@Controller控制层,接收请求,对请求进行处理,并进行响应

@Service业务逻辑层,处理具体的业务逻辑

@Repository数据访问层,也称为持久层。负责数据访问操作

@Configuration配置层,处理项目中的一些配置信息

        和三层架构的对应关系@Controller 对应 表现层,@Service 对应 业务逻辑层,@Repository 对应 数据层

        这里和每个省 / 市都有自己的车牌号一样,车牌号都是唯一的,我们看到车牌,就能知道车主是哪里的了 / 车的归属地,比如 粤X、京X等等。这样做的好处即可以节约号码,还有更重要的作用:标识一辆车的归属地。

        程序的应用分层,调用流程如下:

类注解之间的关系:

        查看@Controller、@Service 、@Repository、@Configuration注解的源码我们发现,它们里面都有一个@Component注解

        这也能说明它们本身就是属于 @Component 的 “子类”。而@Component是一个元注解,也就是说可以注解其他类的注解,如 @Controller、@Service、@Repository 等等,这些注解则被称为 @Component的衍生注解

        @Controller、@Service 和 @Repository 用于更具体的用例(分别为控制层、业务逻辑层、数据访问层),在开发过程中,如果你要在业务逻辑层使用@Component或者@Service,显然@Service是更好的选择

        好比是杯子有喝水的(水杯),也有刷牙的(刷牙杯)等等,但我们更倾向于在日常喝水时使用水杯,洗漱时使用刷牙杯。

更多资料参考:Classpath Scanning and Managed Components :: Spring Framework

3、方法注解 @Bean

        类注解是添加到某个类上的,但是存在两个问题:1、使用外部包里的类,没办法添加类注解。2、一个类,需要多个对象,比如多个数据源。这些场景,我们就需要使用方法注解:@Bean

        以下是方法注解@Bean使用的代码:

public class BeanConfig {
    @Bean
    public UserInfo userInfo() {
        UserInfo user = new UserInfo();
        user.setId(6);
        user.setName("zhangsan");
        user.setAge(18);
        return user;
    }
}

        读取bean的代码:

@SpringBootApplication
public class SpringIoC2Application {
    public static void main(String[] args) {
        //获取Spring上下文对象
        ApplicationContext context = SpringApplication.run(SpringIoC2Application.class, args);
        //从Spring中获取对象
        UserInfo userInfo = context.getBean(UserInfo.class);
        //使用对象
        System.out.println(userInfo);
    }
}

        但我们发现,获取不到,程序报错了,如图:

        原因就是方法注解要搭配类注解使用,上面却没有搭配。

        为什么要搭配类注解呢?因为Spring Boot项目会引入非常多的依赖,里面的代码的方法也会有很多注解,如果都进行扫描,那就太耗时了,不如搭配类注解,Spring就知道从哪些类中扫描,大大的提高了性能

(1)方法注解要配合类注解使用

        在Spring框架的设计中,方法注解 @Bean 要配合类注解才能将对象正常的存储到Spring容器中,代码如下:

@Component
public class BeanConfig {
    @Bean
    public UserInfo userInfo() {
        UserInfo user = new UserInfo();
        user.setId(6);
        user.setName("zhangsan");
        user.setAge(18);
        return user;
    }
}

        执行结果如下:

(2)定义多个对象

        对于同一个类,定义多个对象(多个方法使用@Bean注解);比如多数据源的场景,类是同一个,但配置是不同的,指向不同的数据源。

@Component
public class BeanConfig {
    @Bean
    public UserInfo userInfo1() {
        UserInfo user = new UserInfo();
        user.setId(6);
        user.setName("zhangsan");
        user.setAge(18);
        return user;
    }
    
    @Bean
    public UserInfo userInfo2() {
        UserInfo user = new UserInfo();
        user.setId(7);
        user.setName("lisi");
        user.setAge(19);
        return user;
    }
}

        定义了多个对象的话,我们根据类型获取对象,获取的是哪个对象呢?代码如下:

@SpringBootApplication
public class SpringIoC2Application {
    public static void main(String[] args) {
        //获取Spring上下文对象
        ApplicationContext context = SpringApplication.run(SpringIoC2Application.class, args);
        //从Spring中获取对象
        UserInfo userInfo = context.getBean(UserInfo.class);
        //使用对象
        System.out.println(userInfo);
    }
}

        执行结果,可以看到,报错了:

        可以看到,报错信息显示期望只有一个匹配,结果发现两个:userInfo1,userInfo2。从报错信息中,可以看出来,@Bean注解的bean,bean的名称就是它的方法名

        我们现在改一下代码,根据名称来获取bean对象,代码如下:

@SpringBootApplication
public class SpringIoC2Application {
    public static void main(String[] args) {
        //获取Spring上下文对象
        ApplicationContext context = SpringApplication.run(SpringIoC2Application.class, args);
        //从Spring中获取对象
        UserInfo userInfo1 = (UserInfo) context.getBean("userInfo1");
        UserInfo userInfo2 = (UserInfo) context.getBean("userInfo2");
        //使用对象
        System.out.println(userInfo1);
        System.out.println(userInfo2);
    }
}

        运行结果如下:

        可以看到,@Bean可以针对同一个类,定义多个对象。

(3)重命名 Bean

        可以通过设置 name 属性,给Bean对象进行重命名操作,代码如下:

@Component
public class BeanConfig {
    @Bean(name = {"u1", "userInfo1"})
    public UserInfo userInfo1() {
        UserInfo user = new UserInfo();
        user.setId(6);
        user.setName("zhangsan");
        user.setAge(18);
        return user;
    }
}

        此时使用 u1 就可以获取到User对象了,代码如下:

@SpringBootApplication
public class SpringIoC2Application {
    public static void main(String[] args) {
        //获取Spring上下文对象
        ApplicationContext context = SpringApplication.run(SpringIoC2Application.class, args);
        //从Spring上下文中获取对象
        UserInfo u1 = (UserInfo)context.getBean("u1");
        //使用对象
        System.out.println(u1);
    }
}

        运行结果如下:

        使用 useInfo1 也可以获取到User对象,两个字符串都是对UserInfo的重命名,代码如下:

@SpringBootApplication
public class SpringIoC2Application {
    public static void main(String[] args) {
        //获取Spring上下文对象
        ApplicationContext context = SpringApplication.run(SpringIoC2Application.class, args);
        //从Spring上下文中获取对象
        UserInfo u1 = (UserInfo)context.getBean("userInfo1");
        //使用对象
        System.out.println(u1);
    }
}

        执行结果:

        其中,@Bean中的name也可以省略,代码如下:

@Component
public class BeanConfig {
    @Bean({"u1", "userInfo1"})
    public UserInfo userInfo1() {
        UserInfo user = new UserInfo();
        user.setId(6);
        user.setName("zhangsan");
        user.setAge(18);
        return user;
    }
}

        只有一个名称时,{ } 也可以省略,代码如下:

@Component
public class BeanConfig {
    @Bean("u1")
    public UserInfo userInfo1() {
        UserInfo user = new UserInfo();
        user.setId(6);
        user.setName("zhangsan");
        user.setAge(18);
        return user;
    }
}

4、扫描路径

        现在有个问题,就是不管啥类,只要搭配了五大注解或者五大注解+Bean,Spring就能启动成功吗?

        其实不然,原因就是扫描路径的问题,Spring默认只会对启动类所在的目录下进行扫描,并且扫描的是搭配了五大注解的类或者搭配五大注解+Bean的类

        启动类加了 @SpringBootApplication 注解的类

        现在测试一下,把启动类移动一下,此时启动类所在路径如图:

        

        试试看还能不能获取到UserService对象,UserService类的代码如下:

@Service
public class UserService {
    public void doService() {
        System.out.println("do Service...");
    }
}

        启动柜类代码如下:

@SpringBootApplication
public class SpringIoC2Application {
    public static void main(String[] args) {
        //获取Spring上下文对象
        ApplicationContext context = SpringApplication.run(SpringIoC2Application.class, args);
        //从Spring中获取UserService对象
        UserService userService = context.getBean(UserService.class);
        //使用对象
        userService.doService();
    }
}

        执行结果如下图:

        报错解释没有bean的类型是UserService的

        这里为什么没有找到bean对象呢?原因:即使使用了五大注解,或者五大注解 + @Bean注解,要想生效,还需要配置扫描路径,让Spring扫描到这些注解下的类,也就是通过 @ComponentScan 来配置。加了 @ComponentScan注解 的代码如下:

@ComponentScan({"com.example.springioc2.service"})
@SpringBootApplication
public class SpringIoC2Application {
    public static void main(String[] args) {
        //获取Spring上下文对象
        ApplicationContext context = SpringApplication.run(SpringIoC2Application.class, args);
        //从Spring中获取UserService对象
        UserService userService = context.getBean(UserService.class);
        //使用对象
        userService.doService();
    }
}

        其中注解@ComponentScan的括号里面,加的是UserService类的包路径,直接复制即可,在Service类里面,如下图:

        执行结果如下:

         可以拿到bean对象了。

        其中注解@ComponentScan括号里的 { } ,可以加多个大括号,表示扫描多个路径,如图:

        那为什么之前没有配置 @ComponentScan注解 ,也可以正常启动?原因是: @ComponentScan注解 虽然没有显示配置,但是实际上已经包含在启动类声明注解@SpringBootApplication 中了

        默认扫描的范围是SpringBoot启动类所在包及其子包在配置类添加 @ComponentScan注解,该注解默认会扫描该类所在的包下所有的配置类,如图:

        开发时的推荐做法把启动类放在我们希望扫描的包的路径下,这样我们自己写的代码就都可以被扫描到了,如图:


都看到这了,点个赞再走吧,谢谢谢谢谢

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

鸿蒙开发-ArkTS语言-容器

鸿蒙开发-UI-交互事件-键鼠事件 鸿蒙开发-UI-交互事件-焦点事件 鸿蒙开发-UI-交互事件-手势事件 鸿蒙开发-UI-web 鸿蒙开发-UI-web-页面 鸿蒙开发-ArkTS语言-基础类库 鸿蒙开发-ArkTS语言-并发 鸿蒙开发-ArkTS语言-并发-案例 文章目录 前言 一、容器类库概述 二、线性容器 1…

如何将视频转换成gif表情包?超简单的方法分享

把视频中的片段截取制作成gif动画表情包是现在网络中常见的制作图片的一种方法。Gif表情包能够调节聊天中的氛围&#xff0c;快速有趣的传递信息。也因为gif动图兼容性高、体积小便于分享所以在现在的网络中非常的收欢迎。接下来&#xff0c;小编就给大家分享一下怎么把视频转g…

Linux字符设备驱动(一) - 框架

字符设备是Linux三大设备之一(另外两种是块设备&#xff0c;网络设备)&#xff0c;字符设备就是字节流形式通讯的I/O设备,绝大部分设备都是字符设备&#xff0c;常见的字符设备包括鼠标、键盘、显示器、串口等等&#xff0c;当我们执行ls -l /dev的时候&#xff0c;就能看到大量…

2024.05.06作业

自由发挥应用场景&#xff0c;实现登录界面。 要求&#xff1a;尽量每行代码都有注释。 #include "yuanshen.h"yuanshen::yuanshen(QWidget *parent): QWidget(parent) {//窗口相关设置this->resize(1600,910);this->setFixedSize(1600,910);//窗口标题this-…

管理能力学习笔记九:授权的常见误区和如何有效授权

授权的常见误区 误区一&#xff1a;随意授权 管理者在授权工作时&#xff0c;需要依据下属的能力、经验、意愿问最自己&#xff1a;这项工作适合授权给Ta做吗&#xff1f;如果没有&#xff0c;可以通过哪些方法进行培训呢&#xff1f; 误区二&#xff1a;缺乏信任 心理暗示…

腾讯崛起!2024年最赚钱的电商平台,竟然来自视频号

大家好&#xff0c;我是电商月月 说到卖货平台&#xff0c;这两年“抖音”绝对是所有人心里最赚钱的电商平台 抖音小店的商家利用抖店后台的“精选联盟”引流&#xff0c;不用自己直播&#xff0c;也能靠直播卖货赚的盆满钵满 于是好多平台都效仿抖店的直播卖货形式来获取更…

BGP的选路 :

前提条件 &#xff1a; 丢弃所有不可用的路由信息。 属性的名称 传播范围 默认值 评判标准 PV&#xff08;优选值&#xff09; 不传播 0&#xff08;0-65535&#xff09; 越大越优 LP&#xff08;本地优先级&#xff09; IBGP对等体 之间 100 越大越优 AS_PATH …

中间件研发之Springboot自定义starter

Spring Boot Starter是一种简化Spring Boot应用开发的机制&#xff0c;它可以通过引入一些预定义的依赖和配置&#xff0c;让我们快速地集成某些功能模块&#xff0c;而无需繁琐地编写代码和配置文件。Spring Boot官方提供了很多常用的Starter&#xff0c;例如spring-boot-star…

PMO全面指南:一文读懂PMO的功能、职责、类型、构建

多年来&#xff0c;PMO 的概念在多个行业和类型的组织中越来越受欢迎。一开始&#xff0c;只有大型跨国公司才熟悉它&#xff0c;但后来&#xff0c;许多中小型公司开始采用 PMO 来进行高效的项目管理并实现其战略目标。 根据Statista的数据&#xff0c;目前有80%的组织设有至…

企业网站 | 被攻击时该怎么办?

前言 每天&#xff0c;数以千计的网站被黑客入侵。发生这种情况时&#xff0c;被入侵网站可用于从网络钓鱼页面到SEO垃圾邮件或者其它内容。如果您拥有一个小型网站&#xff0c;很容易相信黑客不会对它感兴趣。不幸的是&#xff0c;通常情况并非如此。 黑客入侵网站的动机与所…

09_电子设计教程基础篇(电阻)

文章目录 前言一、电阻原理二、电阻种类1.固定电阻1、材料工艺1、线绕电阻2、非线绕电阻1、实心电阻1、有机实心电阻2、无机实心电阻 2、薄膜电阻&#xff08;常用&#xff09;1、碳膜电阻2、合成碳膜电阻3、金属膜电阻4、金属氧化膜电阻5、玻璃釉膜电阻 3、厚膜电阻&#xff0…

segformer部分错误

亲测有用 1、TypeError: FormatCode() got an unexpected keyword argument ‘verify‘ mmcv中出现TypeError: FormatCode() got an unexpected keyword argument ‘verify‘-CSDN博客 pip install yapf0.40.0 2、“EncoderDecoder: ‘mit_b1 is not in the backbone regist…

达梦数据库导入数据问题

进行数据导入的时候遇到了导入数据问题 第一个问题&#xff1a; 该工具不能解析此文件&#xff0c;请使用更高版本的工具 这个是因为版本有点低&#xff0c;需要下载最新的达梦数据库 第二个问题&#xff1a; &#xff08;1&#xff09;本地编码&#xff1a;PG_GBK, 导入文…

美特CRM upload.jsp 文件上传致RCE漏洞复现(CNVD-2023-06971)

0x01 产品简介 MetaCRM是一款智能平台化CRM软件,通过提升企业管理和协同办公,全面提高企业管理水平和运营效率,帮助企业实现卓越管理。美特软件开创性地在CRM领域中引入用户级产品平台MetaCRM V5/V6,多年来一直在持续地为客户创造价值,大幅提升了用户需求满足度与使用的满意…

21 内核开发-临界区及临界区代码段判断

内核开发-临界区判断 目录 内核开发-临界区判断 1.定义 2.临界区实现机制 3.使用互斥锁实现临界区的示例 4.怎么识别是临界区代码 5.总结 1.定义 临界区是计算机系统中的一段代码&#xff0c;在任何时刻只能被一个线程执行。临界区的目的是防止多个线程同时访问共享资源…

Make3D数据集相关介绍

一、参考资料 Make3d数据集使用方法 二、相关介绍 1. 简介 Make3D 数据集的每帧图像的深度值均由激光雷达进行采集&#xff0c;相较于 Kinect 相机采集的深度信息&#xff0c;该测距仪可以得到室外图像更加精确的深度信息&#xff0c;而且测距范围更大&#xff0c;与普通的…

【stm32笔记】DSP库调用

参考&#xff1a;DSP库调用 , __CC_ARM,__TARGET_FPU_VFP, __FPU_PRESENT1U, ARM_MATH_CM4把需要的库复制出来单独用&#xff0c;方便移植

websevere服务器从零搭建到上线(三)|IO多路复用小总结和服务器的基础框架

文章目录 epollselect和poll的优缺点epoll的原理以及优势epoll 好的网络服务器设计Reactor模型图解Reactor muduo库的Multiple Reactors模型 epoll select和poll的优缺点 1、单个进程能够监视的文件描述符的数量存在最大限制&#xff0c;通常是1024&#xff0c;当然可以更改数…

什么是X电容和Y电容?

先补充个知识&#xff1a; 一、什么是差模信号和共模信号 差模信号&#xff1a;大小相等&#xff0c;方向相反的交流信号&#xff1b;双端输入时&#xff0c;两个信号的相位相差180度 共模信号&#xff1a;大小相等。方向相同。双端输入时&#xff0c;两个信号相同。 二、安规…

小程序如何重启

用户在使用小程序的过程中&#xff0c;有时候会碰到一些问题。比如小程序数据不加载、卡顿、崩溃或者出现其他异常情况。这时候&#xff0c;最简单的办法就是重启小程序。但是很多客户不知道如何重启小程序&#xff0c;下面就具体介绍小程序重新启动的几种方法。 1. 强制关闭&…