Spring IoCDI(中)--IoC的进步

news2024/11/16 8:12:24

        通过上文的讲解和学习, 我们已经知道了Spring IoC 和DI的基本操作, 接下来我们来系统的学习Spring IoC和DI 的操作. 前⾯我们提到IoC控制反转,就是将对象的控制权交给Spring的IOC容器,由IOC容器创建及管理对 象,也就是bean的存储。

1. Bean的存储

        在之前的代码学习中,要把某个对象交给IOC容器管理,需要在类上添加⼀个注解: @Component ,⽽Spring框架为了更好的服务web应⽤程序, 提供了更丰富的注解. 共有两类注解类型可以实现:

        1. 类注解:@Controller、@Service、@Repository、@Component、@Configuration.

        2. ⽅法注解:@Bean

1.1 @Controller(控制器存储)

        使⽤ @Controller 存储 bean 的代码如下所⽰:

package com.example.zxslzw2014_8_11.controller;

import org.springframework.stereotype.Controller;

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

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

package com.example.zxslzw2014_8_11;

import com.example.zxslzw2014_8_11.controller.UserController;
import com.example.zxslzw2014_8_11.controller.UserController1;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;

@SpringBootApplication
public class Zxslzw2014811Application {

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

    }

}

         ApplicantContent ,即Spring 上下文。因为对象交给Spring管理了,所以获取对象要从Spring中获取,那么就得先得到Spring的上下文。

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

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

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

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

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

1.1.1 获取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会给管理的对象起一个名字。所以给每个对象都起一个名字,然后根据Bean的名称(BeanId)就可以获取到对应的对象。

1.1.2 Bean 命名约定

        官方文档:Bean Overview :: Spring Framework

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

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

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

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

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

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

package com.example.zxslzw2014_8_11;


import com.example.zxslzw2014_8_11.controller.UserController;
import com.example.zxslzw2014_8_11.controller.UserController1;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;

@SpringBootApplication
public class Zxslzw2014811Application {

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

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


         运行结果如下:

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

ApplicationContext 和 BeanFactory (常见面试题)

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

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

1.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删掉,会报错,如图: 

        报错原因如上所示; 

1.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去掉,会报错,原因如上所示;

1.4 @Component(组件存储)

        使用@Component存储bean的代码:

package com.example.zxslzw2014_8_11;

import org.springframework.stereotype.Component;

@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去掉,报错和上面的一样

1.5 @Configuration(配置存储)

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

package com.example.zxslzw2014_8_11;

import org.springframework.context.annotation.Configuration;

@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. 类注解的说明

2.1 为什么有这么多的注解

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

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

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

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

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

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

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

2.2 类注解之间的关系

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

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

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

3. 方法注解 @Bean

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

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

public class BeanConfig {
    @Bean
    public UserInfo userInfo() {
        UserInfo user = new UserInfo();
        user.setId(6);
        user.setName("shenmengyao");
        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就知道从哪些类中扫描,大大的提高了性能。

3.1 方法注解要配合类注解使用

        在Spring框架的设计中,方法注解 @Bean 要配合类注解才能将对象正常的存储到Spring容器中,在之前的代码的类名前面加上@component注解:

package com.example.zxslzw2014_8_11;

import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;

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

        运行结果如下:

 3.2 定义多个对象

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

package com.example.zxslzw2014_8_11;

import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;

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

    @Bean
    public UserInfo userInfo1() {
        UserInfo user = new UserInfo();
        user.setId(7);
        user.setName("yuanyiqi");
        user.setAge(19);
        return user;
    }

}

        定义多个对象的话,我们根据类型获取对象,获取的是哪个对象呢?代码和上面之前的一样,不变,运行代码结果如下:

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

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

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

        运行结果如下,可以看到,@Bean可以针对同一个类,定义多个对象。 

 

3.3 重命名 Bean

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

package com.example.zxslzw2014_8_11;

import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;

@Component
public class BeanConfig {
    @Bean(name = {"u1", "userInfo"})
    public UserInfo userInfo() {
        UserInfo user = new UserInfo();
        user.setId(6);
        user.setName("shenmengyao");
        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 userinfo = (UserInfo)context.getBean("userInfo1");
        //使用对象
        System.out.println(userinfo );
    }
}

 

        上面中同样的输出结果,但是关于@bean注解我们也可以修改成为以下的代码:

        如上图所示,@Bean中的name也可以省略;只有一个名称时,{ } 也可以省略;

4. 扫描路径

        我们来思考只要搭配了五大注解或者五大注解+Bean,Spring就能启动成功吗?

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

        启动类:加了 @SpringBootApplication 注解的类

        现在测试一下,把启动类移动一下,获取到UserService对象,我们发现如下报错信息:

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

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

package com.example.zxslzw2014_8_11.service;


import com.example.zxslzw2014_8_11.UserInfo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.ComponentScan;

@ComponentScan({"com.example.zxslzw2014_8_11"})
@SpringBootApplication
public class Zxslzw2014811Application {

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

    }
}


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

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

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

        故此,一般我们把启动类放在我们希望扫描的包的路径下,这样我们自己写的代码就都可以被扫描到了,

ps:本次的内容就到这里了,如果对你有所帮助的话,就请一键三连哦!!!

本文的封面来自:bilibili苏杉杉的pv,侵权删 url:https://www.bilibili.com/video/BV1vo4y167eh/?spm_id_from=333.999.0.0&vd_source=866da5be2ef0ddd213b053523da53138
————————————————

电子签名:上嘉路

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

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

相关文章

Datawhale AI 夏令营第四期 大模型技术-微调 task3 数据增强与评分

前面我们介绍了baseline的思路及写作方案&#xff0c;这里我们尝试对数据做增强&#xff0c;但是需要聪明的你加入自己的努力完成更好的思路。 今天需要大家学习上手尝试数据增强&#xff0c;不过我会把增强的思路和相关知识告诉大家&#xff0c;让大家学习如何使用llm完成数据…

Ugandan Knuckles

目录 一、题目 二、思路 三、payload 四、思考与总结 一、题目 <!-- Challenge --> <div id"uganda"></div> <script>let wey (new URL(location).searchParams.get(wey) || "do you know da wey?");wey wey.replace(/[<…

铁电存储器(FM24W256)I2C读写驱动(4):I2C读写测试

0 参考资料 FM24W256&#xff08;Cypress公司生产&#xff09;数据手册 1 I2C读写测试 1.1 简单测试方法 使用前面我们设计好的读写驱动&#xff0c;向FM24W256起始地址为0xF0存储区域写入16字节数据“ABCDEFGHIJK12345”&#xff0c;断电后再读取出来&#xff0c;查看读写是…

MySQL基础练习题48-连续出现的数字

目录 题目 准备数据 分析数据 题目 找出所有至少连续出现三次的数字。 准备数据 ## 创建库 create database db; use db;## 创建表 Create table If Not Exists Logs (id int, num int)## 向表中插入数据 Truncate table Logs insert into Logs (id, num) values (1, 1) i…

Autodesk Maya 2019 for Mac/Win:专业三维动画制作软件的巅峰之作

Autodesk Maya 2019是一款世界顶级的三维动画制作软件&#xff0c;专为Mac和Windows系统打造&#xff0c;广泛应用于影视广告、角色动画、电影特技等专业领域。其强大的功能和灵活的工具集&#xff0c;使得用户能够高效地完成复杂的三维建模、动画设计、特效制作及高质量渲染等…

Nginx--代理与负载均衡(扩展nginx配置7层协议及4层协议方法、会话保持)

前言&#xff1a;本博客仅作记录学习使用&#xff0c;部分图片出自网络&#xff0c;如有侵犯您的权益&#xff0c;请联系删除 一、代理原理 1、反向代理产生的背景 单个服务器的处理客户端&#xff08;用户&#xff09;请求能力有一个极限&#xff0c;当接入请求过多时&#…

VirtualBox上的Oracle Linux虚拟机安装Docker全流程

1.安装docker依赖 yum install -y yum-utils device-mapper-persistent-data lvm2 2.安装docker仓库 yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo 生成docker的yum源配置到在 /etc/yum.repos.d/docker-ce.repo 3.安装D…

【软件测试】单元测试20套练习题

&#xff08;一&#xff09;概述 使用Java语言编写应用程序&#xff0c;设计测试数据&#xff0c;完成指定要求的白盒测试&#xff0c;对测试数据及相应测试结果进行界面截图&#xff0c;将代码以及相关截图粘贴到白盒测试报告中。 &#xff08;二&#xff09;题目要求

Keepalived秘籍保障系统高可用的终极武器

目录 一 高可用集群 1.1 集群类型 1.2 实现高可用 1.3 vrrp&#xff08;Virtual Router Redundancy Protocol&#xff09; 二 keepalived 部署 2.1 简介 2.2 keepalived 架构 2.3 keepalived 搭建 三 keepalived 应用示例 3.1 实现master/slave的keepalived单主架构 …

韩顺平老师Python学习笔记【持续更新...】

1、Python语言概述 1.1、转义字符 1.1.1、常用的转义字符 常用转义字符列表 \t一个制表位&#xff0c;实现对齐的功能\n换行符\\一个\\一个\"一个"\r一个回车 1.2、注释 1.2.1、单行注释 # 其他 1.2.2、多行注释 三个单引号 xxx 或 三个双引号 "…

ESLint详解及在WebStorm中的应用

ESLint是一个开源的JavaScript代码检查工具&#xff0c;用于识别和报告JavaScript代码中的模式问题。它可以帮助开发者遵循一定的编码规范和最佳实践&#xff0c;提高代码质量和可维护性。 ESLint的工作原理是通过插件和配置文件来定义一系列规则&#xff0c;对JavaScript代码…

Jakarta Servlet 到 SpringMVC

Jakarta EE&#xff08;曾被称为Java EE&#xff09;是Java平台企业版&#xff08;Java Platform Enterprise Edition&#xff09;的下一代版本&#xff0c;它在Oracle将Java EE的开发和维护交给Eclipse Foundation后得以重生&#xff0c;并更名为Jakarta EE。Jakarta EE保留了…

Redis面试问题(牛客整理版)未完成

文章目录 参考资料出处 缓存过期时间缓存过期删除定期删除 从库处理过期 key持久化过期时间如何确定 缓存淘汰策略LRULFU 缓存模式Cache Aside删除缓存延迟双删 缓存一致性问题解决缓存穿透、击穿和雪崩问题缓存穿透回写特殊值布隆过滤器 缓存击穿Singleflight 缓存雪崩过期时间…

k3s中通过kuboard搭建rabbitmq

如果仅仅是单个rabbitmq容器在单台服务上运行&#xff0c;并不是搭建rabbitmq集群&#xff0c;则不需要使用到service。仅仅通过容器暴露端口到宿主机的形式。 1、拉取 RabbitMQ 镜像 我这边选择的版本是 rabbitmq:3.12-management在终端中执行以下命令以拉取 rabbitmq:3.12-m…

两道关于xssDOM型的案例

第一道 代码分析&#xff1a;data是要插入到html页面的标签及属性&#xff0c;下面的for循环的作用则是将你插入的标签里的属性给全部删除。 图中&#xff0c;把我img的src属性给删掉了。 但当我多写几个属性时&#xff0c;奇怪的事情发生了。 他只把我得src给删掉了&#xff…

SQL基础教程(八)SQL高级处理

※食用指南&#xff1a;文章内容为《SQL基础教程》系列学习笔记&#xff0c;该书对新手入门非常友好&#xff0c;循序渐进&#xff0c;浅显易懂&#xff0c;本人主要用来补全学习MySQL中未涉及的部分&#xff0c;便于刷题和做项目。 官方电子书&#xff1a;《SQL基础教程》第2…

掌握TCP连接管理与流量控制:从零开始

文章目录 1. TCP连接管理1.1 三次握手&#xff08;Three-way Handshake&#xff09;1.2 四次挥手&#xff08;Four-way Handshake&#xff09;1.3 TCP连接管理的重要性 2. TCP流量控制2.1 滑动窗口&#xff08;Sliding Window&#xff09;2.2 拥塞控制&#xff08;Congestion C…

【ARM+Codesys 客户案例 】基于RK3568/A40i/STM32+CODESYS开发的控制器在自动输送分拣系统上的应用,支持定制

2021年“京东618” 累计下单金额超3438亿元,再次刷新纪录! 从下单到收货&#xff0c;各种货品均可在短短几天内通过四通八达的物流网络送达全国任何一个家庭。电子商务和快递物流的迅猛发展对仓储、分拣、配送效率和准确性均提出了更高的要求&#xff0c;加速了智能物流的发展。…

Java Resilience4j-RateLimiter学习

一. 介绍 Resilience4j-RateLimiter 是 Resilience4j 中的一个限流模块&#xff0c;我们对 Resilience4j 的 CircuitBreaker、Retry 已经有了一定的了解&#xff0c;现在来学习 RateLimiter 限流器&#xff1b; 引入依赖&#xff1b; <dependency><groupId>io.g…

序列建模之循环和递归网络 - 递归神经网络篇

序言 在序列建模的广阔领域中&#xff0c;递归神经网络&#xff08; Recursive Neural Network, RNN \text{Recursive Neural Network, RNN} Recursive Neural Network, RNN&#xff09;&#xff0c;注意此处的 RNN \text{RNN} RNN与常用于序列处理的循环神经网络在命名上有所…