从注解入手理解springboot原理

news2024/11/16 12:01:14

一、理解注解

1、注解是什么?

注解可以理解为一个标记或者标签,范围可以是类、方法、属性。

2、自定义一个注解,进行理解spring的自动装配。

自定义自己的注解:JDK官方提供提供了一些基础元注解,就是标记注解的注解。

2.1 查看spring如何写注解

例如Controller注解:
在这里插入图片描述
例如Override注解

@Target(ElementType.METHOD) 
 //标记为方法上的注解,只能在方法上使用,如果在类上使用会报错。
@Retention(RetentionPolicy.SOURCE)
public @interface Override {
}

2.2 自行写一个注解

(1)写一个MyAnnotation 注解。

@Target(ElementType.TYPE) //标记该注解的类型。可以注解
@Retention(RetentionPolicy.RUNTIME) //标记该注解生命周期
@Documented
@Inherited  //标记为可继承性
public @interface MyAnnotation {
    //字段,通过方法的声明方式体现
     String name();
     int age() default 18;
     String hello() default "spring boot";
}

(2)注解的使用

/**
 * @Author taochui
 * @Description: 自行写的注解进行使用
 * @Date: 2022/12/6 10:32
 */
@MyAnnotation(name = "tc",age = 18) //可以设置值
public class UseAnnotation {
}

(3)测试

public class Test {
    public static void main(String[] args) {
        //1、获取需要解析注解的类
        Class<UseAnnotation> useAnnotationClass = UseAnnotation.class;
        //2.判断该类上是否有注解
        if(useAnnotationClass.isAnnotationPresent(MyAnnotation.class)){
            //3、获取该类上的注解
            MyAnnotation annotation = useAnnotationClass.getAnnotation(MyAnnotation.class);
            //4、打印useAnnotationClass上的MyAnnotation注解的内容
            System.out.println(annotation.name() + ":"+annotation.age());
        }

    }
}

(4)结果打印:
在这里插入图片描述

三、xml和注解获取Bean,@Configuration注解理解

3.1 xml获取Bean

resources下新建applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">


    <context:component-scan base-package="com.redair.train.domain"/>
    <bean id="user" class="com.redair.train.domain.User">
        <property name="name" value="strangeBug"></property>
        <property name="age" value="18"></property>
        <property name="id" value="1"></property>
    </bean>

</beans>

3.2 注解获取bean,@Configuration注解实现一个配置类

MyConfiguration 注解类,@Configuration使该class成为配置类。 @Bean使该类成为Bean,由IOC容器管理。

@Configuration
public class MyConfiguration {
    @Bean
    public User user(){
        User user = new User();
        user.setName("tc");
        user.setAge(22);
        user.setId(2L);
        return user;
    }
}

3.3 测试xml和注解获取Bean

public class Test {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext conetxt = new ClassPathXmlApplicationContext("applicationContext.xml");
        User user = conetxt.getBean(User.class);
        System.out.println("xml文件获取bean:"+user);

        AnnotationConfigApplicationContext configContext = new AnnotationConfigApplicationContext(MyConfiguration.class);
        User user1 = (User)configContext.getBean("user");
        System.out.println("注解形式获取bean:"+user1);

    }
}

结果:
在这里插入图片描述

思考:那如果需要装配的Bean太多,不能疯狂的写Bean,都这么写就很麻烦。引出ComponentScan注解和Import。

四、 ComponentScan注解

使用ComponentScan扫描某个包下的所有Bean。

@Configuration
@ComponentScan("com.redair.train.domain")
public class MyConfiguration01 {

}

domain下示列:

@Data
@Controller("user")
public class User {
    private Long id;
    private String name;
    private Integer age;
}

测试:

public class Test {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext configContext = new AnnotationConfigApplicationContext(MyConfiguration01.class);
        User user1 = (User)configContext.getBean("user");
        System.out.println("ComponentScan注解形式扫描获取bean:"+user1);
    }
}

打印ComponentScan注解形式扫描获取bean:
在这里插入图片描述

五、@Import注解

比如我现在有多个配置类MyConfig01和MyConfig02,如何通过一个配置类MyConfiguration获取多个配置类。
通过一个配置类得到所有Bean。

@Configuration
public class MyConfig01 {
    @Bean
    public User user(){
        return new User();
    }
}
@Configuration
public class MyConfig02 {
    @Bean
    public Student student(){
        return new Student();
    }
}

使用Import导入另外两个类中的Bean,使得到一个类中可以获取。多个配置类合并成一个配置类。

@Configuration
@Import({MyConfig01.class,MyConfig02.class})
public class MyConfig {
}

测试:
public class TestMyConfig {
public static void main(String[] args) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(MyConfig.class);
for(String s : context.getBeanDefinitionNames()){
System.out.println(“打印出MyConfig下所有Bean:”+s);
}
}
}

结果:
在这里插入图片描述

六、理解和spring源码思路

为什么加入Controller注解,就能够被IOC容器进行管理。
@Controller
public class HelloController {

@RequestMapping("/test")
@ResponseBody
public String index(){
    return "Hello spring";
}

}

IOC容器其实就是一个Map集合,通过map.put(“id”,“对象”)加入到IOC容器。

分析到目前,spring源码思路:
1、解析app.xml文件
2、Bean–>反射方式创建对象–>map.put(“user”,user)
例如@Autowired。即map.get(“user”);
3、XML<context:component-scan base-package=“com.redair.train.domain”/>或者
注解@ComponentScan(“com.redair.train.domain”)。两种(XML或者注解)方式扫描包下到底哪些类上加了Controller注解。则认为是IOC容器进行管理, 则反射创建该对象放入到IOC容器。
3、其实就是根据扫描这些大量的注解,根据注解做出对应的动作。

截止目前为止,我们IOC容器管理Bean几种方式:
1、@Bean
2、@Import({MyConfig01.class,MyConfig02.class})
3、@ComponentScan(“com.redair.train.domain”)。有局限性,只能触达包里面的Bean.
3、但是还有一个问题:我们要管理的Bean,不知道在不在业务范围。比如第三方包,未来会用,不在我们的包里面。com.taobao.xx,com.ali.yy,com.等。
用一个配置类,导入第三方的包,该如何做。比如tomact,Mq,redis等。

解决:使用ImportSelector 中selectImports方法读取外部类。

七、ImportSelector接口中selectImports方法

使用和理解:定义一个MyImportSelector,读取一个Bean打印进行理解。

/**
 * @Author taochui
 * @Description: 实现配置类能够导入第三方包。实现ImportSelector。
 * 根据第三方包或者配置文件寻找得到配置类
 * 使用:Import(MyImportSelector.class)获取到第三方Bean,自动调用selectImports方法获取到Bean。
 * @Date: 2022/12/6 22:49
 */
public class MyImportSelector implements ImportSelector {

    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        return new String[]{"寻找一个spring.factories"};
    }
}

具体使用,实现ImportSelector 中selectImports方法,导入一个配置类。
在这里插入图片描述

1、MyImportSelectorTest ,通过ImportSelector导入user类。

public class MyImportSelectorTest implements ImportSelector {
    @Override
    public String[] selectImports(AnnotationMetadata importingClassMetadata) {
        return new String[]{"com.redair.train.domain.user"};
    }

}

2、通过Import导入MyImportSelectorTest类,获取到里面的Bean。
UserConfig类,配置类。

@Configuration
@Import(MyImportSelectorTest.class)
public class UserConfig {
}

3、测试。获取UserConfig的注册的bean。

public class TestRun {
    public static void main(String[] args) {
        AnnotationConfigApplicationContext configContext = new AnnotationConfigApplicationContext(UserConfig.class);
        for(String s : configContext.getBeanDefinitionNames()){
            System.out.println("UserConfig(通过ImportSelector导入外部或配置文件类)获取bean::"+s);
        }
    }
}

4、打印结果
在这里插入图片描述

八、设计Spring Boot的自动装配

根据上面分析,进行设计
范围:业务代码类 和 第三方类 —>自动被IOC容器进行管理。
大致原理:

@Configuration
@ComponentScan("com.redair.train")   //由ComponentScan导入业务代码类
@Import(MyImportSelectorTest.class)   //由Import导入外部类
public class UserConfig {
}

其中MyImportSelectorTest implements ImportSelector,selectImports方法读取一个配置文件(spring.factories),配置文件中包含Tomcat,Redis等配置信息。

分析@SpringBootApplication注解。
源码:
在这里插入图片描述

查看@SpringBootApplication注解,上面四个为元注解。主要看后面三个,其实就是和上面分析的三个注解对应。

@Configuration
@ComponentScan("com.redair.train")   //由ComponentScan导入业务代码类
@Import(MyImportSelectorTest.class)   //由Import导入外部类

我们分析的三个注解和@SpringBootApplication注解中对应关系:
@Configuration <—> @SpringBootConfiguration
@ComponentScan(“com.redair.train”) <—>@ComponentScan
@Import(MyImportSelectorTest.class) <—>@EnableAutoConfiguration

分析对应关系:
1、点击@SpringBootApplication中@SpringBootConfiguration注解源码如下:
即对应我们分析的注解@Configuration 。
在这里插入图片描述
2、源码中@ComponentScan注解和我们@ComponentScan其实是一样的。
即 @Configuration和@ComponentScan 这两个注解就能完成我们业务代码的扫描。
解析到TrainApplication(运行类)上面的所有注解:

(1)有一个@Configuration--->认为TrainApplication具有配置类的功能。
(2)有哪些Bean呢?当前TrainApplication你们有没有@Bean。
(3)如果有怎么弄过来呢?根据@ComponentScan解析到--->com.redair.train---->当前TrainApplication所在根路径。
(4)扫描  com.redair.train -->得到很多的类。
(5)看这些类上是否有@Controller、@Service、@Repository、@Component --->想要被IOC容器管理---->map.put(id,对象)。

3、springboot 启动,日志打印出Tomcat也启动了,那Tomcat被自动装配了。
其实就是我们分析的外部类导入@Import(MyImportSelectorTest.class) <—>@EnableAutoConfiguration对应。
具体分析:
查看@EnableAutoConfiguration如下,
在这里插入图片描述
核心注解@Import(AutoConfigurationImportSelector.class)和我们分析的@Import(MyImportSelectorTest.class) 一致。

AutoConfigurationImportSelector应该会去实现ImportSelector接口中selectImports方法–>会去寻找spring.factories–>说明我们第三方需要装配的类有哪些?

点击进入AutoConfigurationImportSelector.class
1、查看类关系图,DeferredImportSelector实现了ImportSelector接口:
在这里插入图片描述
2、点击DeferredImportSelector查看。
在这里插入图片描述
一直点击进去能够看到实现了selectImports方法。在这里插入图片描述

//寻找spring.factories文件
AutoConfigurationEntry autoConfigurationEntry = getAutoConfigurationEntry(annotationMetadata);

点击getAutoConfigurationEntry进去。

List<String> configurations = getCandidateConfigurations(annotationMetadata, attributes);
//List集合,有多个spring.factories文件对应的类加入到List集合。

在这里插入图片描述
断点查看:
在这里插入图片描述

继续点击getCandidateConfigurations方法进去:
寻找spring.factories,如果没找到则没找到,并且文件约定位置为META-INF/spring.factories。
在这里插入图片描述
点击loadFactoryNames进去,发现调用loadSpringFactories,其中classLoader.getResources(FACTORIES_RESOURCE_LOCATION);读取配置文件信息spring.factories。
在这里插入图片描述
在这里插入图片描述
接下来把Tomcat这个类所在的spring.factories找到。
因为Tomcat随着springBoot启动而启动,说明它是优先级比较高的,会放在一个包,这个包是autoconfigure。
在这里插入图片描述
第三方需要装配的类就会放到spring.factories文件中。
比如redis,都是以AutoConfiguration结尾的。那么Tomcat就会有一个TomcatAutoConfiguration作为引导类,自动装配和Tomcat相关的类。但是TomcatAutoConfiguration没找到。
![在这里插入图片描述](https://img-blog.csdnimg.cn/c56151c1a95d4d74895eb7b7b1186991.png
原因:因为springboot容器不止有Tomcat,还有jetty、undertow,那就直接用一个ServletWebServerFactoryAutoConfiguration引导类引导这些容器。
在这里插入图片描述
点击进去:
发现确实可以引导Tomcat、jetty、undertow三种容器的创建。
在这里插入图片描述
如果太多,可以在pom中进行排除,比如把Tomcat排除,就不会引导Tomcat的IOC化。在这里插入图片描述
是不是在spring.factories文件中配置的第三方所有类的全路径都会引导IOC容器话吗?
其实不是!!!
spring应该提供一个功能,让开发者可以有选择的去转载Bean,根据某些条件转载Bean。
比如Tomcat,还有一个条件注解,满足该注解才进行装配。

@ConditionalOnClass(name = "org.apache.catalina.startup.Tomcat")

满足org.apache.catalina.startup.Tomcat能够找到Tomcat才进行装载。
@Conditional注解去判断满足条件才进行IOC容器管理。

@Conditional,设计很多原则判断是否进行进行IOC容器管理。
1、写一个MyCondition条件判断
/**

  • @Author taochui
  • @Description: 自行写一个MyCondition条件判断,是否进行IOC容器化
  • @Date: 2022/12/7 1:16
    */
    public class MyCondition implements Condition {
    @Override
    public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) {
    不创建。如何是true,表示创建
    return false;
    }
    }

2、使用@Conditional条件装配进行判断
@Configuration
public class ConditionConfig {
@Bean
@Conditional(MyCondition.class)
public User user(){
User user = new User();
user.setName(“tc”);
return user;
}
}

3、测试
public class Test {
public static void main(String[] args) {
AnnotationConfigApplicationContext configContext = new AnnotationConfigApplicationContext(MyCondition.class);
User user1 = (User)configContext.getBean(“user”);
System.out.println(“条件装配测试是否装配:”+user1);
}
}

4、结果,找不到这个Bean。
springboot核心还是spring,只是加上了springboot特有的东西
(1)创建spring context。
(2)创建Listener。
(3)IOC初始化把Bean都转载进来。
(4)DI 依赖注入。

根据应用类型决定接下来的spring上下文的解析方式。

static WebApplicationType deduceFromClasspath() {
	if (ClassUtils.isPresent(WEBFLUX_INDICATOR_CLASS, null) && !ClassUtils.isPresent(WEBMVC_INDICATOR_CLASS, null)
			&& !ClassUtils.isPresent(JERSEY_INDICATOR_CLASS, null)) {
		return WebApplicationType.REACTIVE;
	}
	for (String className : SERVLET_INDICATOR_CLASSES) {
		if (!ClassUtils.isPresent(className, null)) {
			return WebApplicationType.NONE;
		}
	}
	return WebApplicationType.SERVLET;
}
context = createApplicationContext();
context.setApplicationStartup(this.applicationStartup);
prepareContext(bootstrapContext, context, environment, listeners, applicationArguments, printedBanner);
refreshContext(context);
afterRefresh(context, applicationArguments);

上下文的context的处理阶段:
create 创建
prepare 准备
refresh 刷新 —>真正的核心
afterRefresh 刷新后

refresh 刷新 —>真正的核心
思路:
IOC容器 Map集合 (里面的属性,依赖注入、xml 、@value 、 @Reference)
Listeners 监听器
env 环境变量
支持国际化
包换Tomcat的启动过程(通过自动装配把tomcat的类搞进IOC容器,启动而启动)
前置后置的处理

refreshContext(context);
在这里插入图片描述

在这里插入图片描述
BeanFactory是xml、注解上下文顶层的接口。

在这里插入图片描述
不同的应用类型调用不同的方法。我们用的第三个web。
核心源码:
在这里插入图片描述
核心:

	// Initialize other special beans in specific context subclasses.
		onRefresh();

在这里插入图片描述
在这里插入图片描述

可以实现ApplicationRunner方法,启动时执行。

@SpringBootApplication
public class TrainApplication implements ApplicationRunner {

    public static void main(String[] args) {
        SpringApplication.run(TrainApplication.class, args);
        System.out.println("******************************启动springBoot******************************");
        System.out.println("**********************");

    }

    @Override
    public void run(ApplicationArguments args) throws Exception {
        System.out.println("启动时执行");
    }
}

在这里插入图片描述

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

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

相关文章

Android设计模式详解之状态模式

前言 状态模式中的行为是由状态来决定的&#xff0c;不同的状态下有不同的行为。 状态模式和策略模式的结构几乎完全一样&#xff0c;但他们的目的、本质却完全不一样。 状态模式的行为是平行的、不可替换的&#xff0c;而策略模式的行为是彼此独立、可互相替换的。 状态模式把…

满足耐压24V的USB3.0 USB3.1 Type-C防静电器件

什么是USB3.1 Type-C 现有的USB 2.0协议允许高达480Mbps的数据传输速率&#xff0c;并支持即插即用、热插拔安装和运行。与之相比&#xff0c;USB 3.0规范允许高达5Gbps的数据传输速率&#xff0c;并向后支持较低速的USB 2.0规范。 USB 3.0增加了4个接到连接器的新引脚&#…

湖北移动M411A_ZN-S905L3AB-UWE5621DS原机制作语音线刷包

湖北移动M411A_ZN-S905L3AB-UWE5621DS原机制作语音线刷包&#xff0c;打开原机屏蔽的WIFI&#xff0c;设置、首页、语音正常。 固件特点&#xff1a; 1、修改dns&#xff0c;三网通用&#xff1b; 2、开放原厂固件屏蔽的市场安装和u盘安装apk&#xff1b; 3、无开机广告&am…

非零基础自学Golang 第16章 正则表达式 16.1 正则表达式介绍 16.2 正则表达式语法

非零基础自学Golang 文章目录非零基础自学Golang第16章 正则表达式16.1 正则表达式介绍16.2 正则表达式语法16.2.1 普通字符16.2.2 字符转义16.2.3 元字符16.2.4 限定符16.2.5 定位符16.2.6 分组构造16.2.7 匹配模式第16章 正则表达式 正则表达式&#xff08;Regular Expressi…

Docker高级:Redis集群实战!4主4从缩容到3主3从,怎么处理?

在上一篇,我们学会了redis集群的扩容。从3主3从扩容到4主4从。 那么,接着,活动过去了。流量没有那么大了。需要缩容了。从4主4从缩容到3主3从了。那么这个时候又该怎么处理呢? PS本系列:《Docker学习系列》教程已经发布的内容,凯哥会在文末加上。 缩容思考问题: 1:…

TypeScript 前端工程最佳实践

作者&#xff1a;王春雨 前言 随着前端工程化的快速发展&#xff0c; TypeScript 变得越来越受欢迎&#xff0c;它已经成为前端开发人员必备技能。 TypeScript 最初是由微软开发并开源的一种编程语言&#xff0c;自2012年10月发布首个公开版本以来&#xff0c;它已得到了人们…

Docker自定义镜像上传阿里云

目录 1. alpine 简介 2. 基于alpine构建jdk8镜像 2.1 Dockerfile 2.2 将构建目录上传到linux中 2.3 执行构建 3. 镜像瘦身 4. 上传阿里云镜像仓库 1. alpine 简介 Alpine Linux是一个轻型Linux发行版&#xff0c;它不同于通常的Linux发行版&#xff0c;Alpine采用了mus…

斯坦福联合Meta提出多模态模型RA-CM3,检索增强机制或成文本图像领域新制胜法宝

原文链接&#xff1a;https://www.techbeat.net/article-info?id4403 作者&#xff1a;seven_ 论文链接&#xff1a; https://arxiv.org/abs/2211.12561 相信目前很多AI大模型研究者都会遇到一个非常困难的问题&#xff0c;那就是很难控制的模型参数和容量&#xff0c;由于参与…

【Three.js入门】纹理及其常用属性、透明纹理、环境遮挡贴图与强度

个人简介 &#x1f440;个人主页&#xff1a; 前端杂货铺 &#x1f64b;‍♂️学习方向&#xff1a; 主攻前端方向&#xff0c;也会涉及到服务端 &#x1f4c3;个人状态&#xff1a; 在校大学生一枚&#xff0c;已拿多个前端 offer&#xff08;秋招&#xff09; &#x1f680;未…

消息队列—RabbitMQ(万字详解)

消息队列—RabbitMQ 笔记整理自 【涛哥】最适合小白入门的RabbitMQ教程 1. 消息队列介绍 Ⅰ. 消息队列需求场景 在基于微服务开发的电商项目中&#xff0c;商品的查询和商品的修改是通过两个服务实现的&#xff0c;如果修改了商品的价格&#xff0c;如何保证商品查询服务查询出…

矢量网络分析仪如何测量史密斯图及滤波器的带宽?

矢量网络分析仪是一种很神奇的测量仪器&#xff0c;它的功能很强大也值得人们去探索。今天&#xff0c;安泰测试工程师就针对矢量网络分析仪中的史密斯图及滤波器的带宽测量进行简单的介绍&#xff0c;希望能够让更多的人对此有所了解&#xff0c;并产生兴趣。 首先仪器了解一下…

数字孪生可视化图表:了解堆叠的条形图

数据可视化已成为我们日常数据分析工作当中的重要组成部分&#xff0c;可视化大屏是数据可视化发展的产物。这又不得不说到一个概念&#xff1a;可视化组件。可视化组件是制作数字孪生可视化大屏必不可少的一部分&#xff0c;在一个完整的数字孪生可视化大屏中用到的图表可不少…

Android系统之路(初识MTK) ------Android11.0给辅助工具-手电筒添加低电Toast提醒

Android11.0给辅助工具-手电筒添加低电Toast提醒 今天因为在复测昨天的一个monkey压测并且还没测完,所以打算记录最近做系统开发的一些心得和经验,也记录一下自己的系统开发历程 修改前的效果图: 修改后的效果图: 后期补上… 修改前当电量小于等于15%时,按钮依旧可以打…

11条非常实用的Git 和 Git 命令,值得你收藏

基本命令 01. init git init 在当前目录中创建一个新的空仓库。 02. clone git clone https://github.com/facebook/react.git 将远程存储库复制到当前目录。 03. add git add 命令将工作目录中的新文件或更改的文件添加到 Git 暂存区。 git add <file1> <file2&…

【WAF绕过-4】漏洞利用之注入上传跨站等绕过

1、SQL注入 如需sqlmap注入测试&#xff0c; 防cc拦截&#xff1a;修改user-agent头代理&#xff08;付费代理池&#xff09; 修改user-agent头&#xff1a; &#xff08;1&#xff09;加参数&#xff1a;--random-agent &#xff08;2&#xff09;加参数&#xff1a;--user-a…

几十年前的老旧照片如何修复?还不知道旧照片怎么恢复清晰吗?

那些旧照片本身会随着时间的推移而褪色、褶皱。老旧照片修复主要是从褪色、变色、破损、发霉、的旧相片修复翻新&#xff0c;到模糊不清清晰化处理&#xff0c;大面积严重破损照片修补。 十年以前&#xff0c;没有电脑&#xff0c;没有手机&#xff0c;更没有存储照片工具。大…

【关于时间序列的ML】项目 5 :用机器学习预测天气

&#x1f50e;大家好&#xff0c;我是Sonhhxg_柒&#xff0c;希望你看完之后&#xff0c;能对你有所帮助&#xff0c;不足请指正&#xff01;共同学习交流&#x1f50e; &#x1f4dd;个人主页&#xff0d;Sonhhxg_柒的博客_CSDN博客 &#x1f4c3; &#x1f381;欢迎各位→点赞…

基于Canal+kafka监听数据库变化的最佳实践

1、前言 工作中&#xff0c;我们很多时候需要根据某些状态的变化更新另一个业务的逻辑&#xff0c;比如订单的生成&#xff0c;成交等&#xff0c;需要更新或者通知其他的业务。我们通常的操作通过业务埋点、接口的调用或者中间件完成。 但是状态变化的入口比较多的时候&#x…

位图详解.

1.位图概念 给40亿个不重复的无符号整数&#xff0c;没排过序。给一个无符号整数&#xff0c;如何快速判断一个数是否在这40亿个数中&#xff1f; 思考&#xff1a; 1.用哈希表&#xff1f;遍历一遍&#xff1f;时间复杂度O(N) 40亿个不重复无符号整数占多大内存&#xff1…

springcloud配置中心nacos动态线程池Dynamic-tp配置接入实战

最近业务上需要把项目组几个微服务接入动态线程池框架Dynamic-tp监控&#xff0c;同时支持webhook机器人接受变更通知、容量报警、活性报警、拒绝报警、任务超时报警等通知&#xff0c;方便项目组同事企业微信群实时监控线程池状态&#xff0c;动态调整线程参数。 接手开始上手…