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

(2)SpringBoot自动装配原理简介

SpringBoot自动装配

image-20250129011450796

这里写目录标题

  • SpringBoot自动装配
    • 启动器
    • 主程序
      • 自定义扫描包
      • @SpringBootApplication
        • @SpringBootConfiguration
        • @EnableAutoConfiguration
          • @AutoConfigurationPackage
          • @Import({AutoConfigurationImportSelector.class})选择器
            • AutoConfigurationEntry
            • getCandidateConfigurations
    • 组件添加
      • 代理设置
      • @import注解
      • Conditional注解
      • @ImportResource注解
    • 配置绑定
      • @ConfigurationProperties注解
      • @EnableConfigurationProperties注解
    • 主函数
      • @EnableAutoConfiguration注解
        • @AutoConfigurationPackage注解
        • @Import({AutoConfigurationImportSelector.class})
      • 按需开启
    • 自动装配流程
      • 条件装配流程
      • 修改默认配置

我们通过观察创建的SpringBoot项目的pom.xml文件发现他的核心依赖大部分在他的父工程中,长按ctrl并点击父项目就可以进入到父项目的文件,从浏览器上面下载压缩包的那种创建springBoot方式不能查看夫项目的文件。

spring-boot-dependencies是parent的父项目。

image-20250126232001767

在这里制定了大量的依赖版本,还有过滤器。

我们的pom.xml文件与之前不同的就是我们在引入依赖的时候可以不指定依赖的版本,这就是因为在父工程中指定了依赖的版本,我们没必要再写。当然,如果要引入他没有规定的依赖还是要声明版本的。

如果我们对他的依赖版本不满意,想要使用我们自己的,我们可以指定需要的版本

image-20250127092614695

这个就是修改mysql版本的方法。

启动器

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId>
</dependency>

项目自带的启动器,下面有很多的在他的基础上添加后缀的依赖,比如说-web配置内置的tomcat容器等

访问下面这个网址可以找到对于启动器的介绍

Build Systems :: Spring Boot

image-20250127093321786

image-20250126233141282

这里可以查询到我常用的依赖。如aop,缓存等的,我们也可以使用idea的分析依赖树功能,更好的查看我们项目中的依赖。

image-20250127093608520

主程序

首先alt+回车查看他的返回类型ConfigurableApplicationContext是一个IOC容器,我们通过getBeanDefinitionNames来打印一下它里面的所有组件。

package com.kang.start;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class StartApplication {public static void main(String[] args) {//ConfigurableApplicationContext是一个IOC容器ConfigurableApplicationContext run = SpringApplication.run(StartApplication.class, args);String[] names = run.getBeanDefinitionNames();for (String name:names) {System.out.println(name);}}
}

image-20250127095933200

说明他配置了dispathcer,我们之前学习的基本上所有的组件都可以在这里找到。

自定义扫描包

注意在官网上说的包结构的安排,只有把组件放在项目目录下才能扫描到。

image-20250127150206230

当然想要改变扫描的包也很简单,加一个这个

@SpringBootApplication(scanBasePackages = "com.kang")

image-20250127150607182

当然也有第二种方法就是直接把它里面的注解拽出来,这样配置就不会与SpringBootApplication标签里面的包扫描冲突

/*@SpringBootApplication*/@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan("com.kang")
public class StartApplication {public static void main(String[] args) {ConfigurableApplicationContext run = SpringApplication.run(StartApplication.class, args);String[] names = run.getBeanDefinitionNames();for (String name:names) {System.out.println(name);}}
}

这里我们也可以得出一个结论

@SpringBootApplication
等价于
@SpringBootConfiguration
@EnableAutoConfiguration
@ComponentScan("com.kang")

在 [application.properties] 文件中我们发现,我们点开配置文件的源码以后,里面绑定的都是类,最后这些类都会注入到IOC容器中。

@SpringBootApplication

他的主程序很少,其中最关键的注解就是@SpringBootApplication声明它是springBoot程序,查看他的源文件会发现两个最重要的注解

@SpringBootConfiguration
@SpringBootConfiguration@Configuration@Component//这个注解代表他本质上还是一个spring的组件
@EnableAutoConfiguration
@EnableAutoConfiguration//自动导入配置文件;@AutoConfigurationPackage//自动配置包@Import({AutoConfigurationImportSelector.class})//导入选择器
@AutoConfigurationPackage
@Import({Registrar.class})

image-20250128235521109

通过Regist类我们可以发现的本质就是一个自动注册包的类

@Import({AutoConfigurationImportSelector.class})选择器

这两个配置注解在AutoConfigurationImportSelector这个类中有一个核心语句就是获取所有的配置

List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);
AutoConfigurationEntry

AutoConfigurationEntry获得自动配置的实体

image-20250129001747171

getCandidateConfigurations

了解一下getCandidateConfigurations的

protected List<String> getCandidateConfigurations(AnnotationMetadata metadata, AnnotationAttributes attributes) {ImportCandidates importCandidates = ImportCandidates.load(this.autoConfigurationAnnotation, this.getBeanClassLoader());List<String> configurations = importCandidates.getCandidates();Assert.notEmpty(configurations, "No auto configuration classes found in META-INF/spring/" + this.autoConfigurationAnnotation.getName() + ".imports. If you are using a custom packaging, make sure that file is correct.");return configurations;
}

其中 "No auto configuration classes found in META-INF/spring/"这里说的就是自动配置的核心文件

image-20250127152152077

就是它,点开我们可以看到很多的配置,比如说常见的aop,jdbc等的配置。但是我们点开以后发现很多的都是爆红的,这说明我们并没有配置该组件,我们只要在pom文件中添加依赖,下载完成以后就不爆红了。

image-20250129011450796

组件添加

首先创建实体类

User类

package com.kang.start.pojo;public class User {String name;int age;@Overridepublic String toString() {return "User{" +"name='" + name + '\'' +", age=" + age +'}';}public User() {}public User(String name, int age) {this.name = name;this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}
}

Pet类

package com.kang.start.pojo;public class Pet {String name;public Pet() {}@Overridepublic String toString() {return "Pet{" +"name='" + name + '\'' +'}';}public String getName() {return name;}public void setName(String name) {this.name = name;}public Pet(String name) {this.name = name;}
}

然后注册到容器中的方法有两种

方法一:
配置beans.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"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"><bean id="user01" class="com.kang.start.pojo.User"><property name="age" value="18"/><property name="name" value="zhangsan"/></bean><bean id="Tomcat" class="com.kang.start.pojo.Pet"><property name="name" value="Tomcat"/></bean>
</beans>

方法二:

使用配置类(配置类本身也是组件)+注解

  1. @Configuration//声明配置类==xml文件
  2. @Bean//添加组件,方法名就是id,返回类型就是组件类型,返回值就是对象。
  3. @Bean(“Tom”)//自定义名称
package com.kang.start.config;import com.kang.start.pojo.Pet;
import com.kang.start.pojo.User;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration//声明配置类==xml文件
public class myConfig {@Bean//添加组件,方法名就是id,返回类型就是组件类型,返回值就是对象。public User user01(){return new User("xiaom",18);}@Bean("Tom")//自定义名称public Pet TomcatPet(){return new Pet("Tomcat");}
}

我们在主函数中输出一下

public class StartApplication {public static void main(String[] args) {ConfigurableApplicationContext run = SpringApplication.run(StartApplication.class, args);String[] names = run.getBeanDefinitionNames();for (String name:names) {System.out.println(name);}}
}

image-20250127154604459

得到了我们注册的两个类

代理设置

@Configuration(proxyBeanMethods = true)

proxyBeanMethods参数是设置代理,当他默认值为true的时候,当我们创建两个对象的时候,他们的哈希地址是一样的,设置为false的时候就是不同的。

这就涉及到两种模式:

  1. Full:proxyBeanMethods = true,把创建的对象放在容器中,调用的时候从容器中取出来
  2. Lite:proxyBeanMethods = false,每次调用的时候创建对象。(轻量级模式)

举个例子:如果我们在User对象中绑定一个Pet类型的cat,当我们代理为true的时候,我们绑定的宠物就是容器中的cat,这就成功的让User绑定到了cat,但是如果代理设置为false,那么我们绑定的Pet就是新创建的,并不是我们在配置类中绑定的那个Pet。

总的来说,当我放入IOC的对象存在IOC依赖的时候就需要打开代理,当我们没有IOC依赖的时候就调成false,让我们更快的加载。因为他跳过了在IOC中检测的步骤。

@import注解

这个组件可以帮助我们在IOC容器中创建指定类型的组件

比如说,我们随便import一个组件,是自定义的

@Import({User.class})
@Configuration(proxyBeanMethods = true)
public class myConfig {@Bean//添加组件,方法名就是id,返回类型就是组件类型,返回值就是对象。public User user01(){return new User("xiaom",18);}@Bean("Tom")//自定义名称public Pet TomcatPet(){return new Pet("Tomcat");}
}

输出一下

public static void main(String[] args) {ConfigurableApplicationContext run = SpringApplication.run(StartApplication.class, args);String[] names = run.getBeanNamesForType(User.class);for (String name:names) {System.out.println(name);}}

image-20250127171713282

他的名字就是类地址名。这就代表成功注册了

Conditional注解

他的作用是在指定条件下注册指定的类,看下他的源文件

image-20250127172306288

ctrl+H,我们发现他有很多很多的派生注解。

image-20250127173001574

首先解释一个方法containsBean,它可以检测容器中是否存在指定的类

我们先把tom组件注释掉

public static void main(String[] args) {ConfigurableApplicationContext run = SpringApplication.run(StartApplication.class, args);boolean tom = run.containsBean("tom");System.out.println("输出是否存在组件tom:"+tom);boolean user01 = run.containsBean("user01");System.out.println("输出是否存在组件user01:"+user01);}

image-20250127173638853

我们首先对User和Pet建立依赖

package com.kang.start.pojo;public class User {String name;int age;Pet pet;public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public Pet getPet(Pet pet) {return this.pet;}public void setPet(Pet pet) {this.pet = pet;}public User(String name, int age) {this.name = name;this.age = age;}
}
@Configuration(proxyBeanMethods = true)
public class myConfig {@Bean//添加组件,方法名就是id,返回类型就是组件类型,返回值就是对象。public User user01(){User user = new User("xiaom", 18);user.setPet(TomcatPet());return user;}@Bean("Tom")//自定义名称public Pet TomcatPet(){return new Pet("Tomcat");}
}

使用一个注解@ConditionalOnBean(name = “Tom”)

@Configuration(proxyBeanMethods = true)
public class myConfig {@Bean("Tom")//自定义名称public Pet TomcatPet(){return new Pet("Tomcat");}@ConditionalOnBean(name = "Tom")//检测容器中是否存在Tom,如果存在则创建user01@Bean//添加组件,方法名就是id,返回类型就是组件类型,返回值就是对象。public User user01(){User user = new User("xiaom", 18);user.setPet(TomcatPet());return user;}
}

检测是否存在

image-20250127181448945

当我们注释掉Tom时

image-20250127181529172

user01也不会注册;也可以把它注解在整个类以外,如果存在这个类,下面所有的配置才会生效。

@ImportResource注解

它可以帮助我们自动导入beans.xml文件,比如说,在我们运行一个比较老的项目的时候他的配置用的全都是xml文件注册的bean,我们想要快速的把他的xml文件中的beans注册到我们的IOC容器中,我们就可以使用在各个注解。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"><bean id="hehe" class="com.kang.start.pojo.Pet"><property name="name" value="Tomcat"/></bean><bean id="haha" class="com.kang.start.pojo.User"><property name="age" value="18"/><property name="name" value="zhangsan"/></bean>
</beans>

这样一个xml文件

@Configuration(proxyBeanMethods = true)
@ImportResource("classpath:beans.xml")//快速引入指定的bean注册文件
public class myConfig {@Bean("Tom")//自定义名称public Pet TomcatPet(){return new Pet("Tomcat");}@ConditionalOnBean(name = "Tom")@Bean//添加组件,方法名就是id,返回类型就是组件类型,返回值就是对象。public User user01(){User user = new User("xiaom", 18);user.setPet(TomcatPet());return user;}
}

image-20250127182738665

配置绑定

@ConfigurationProperties注解

简单来说就是使用Java读取到propertie文件中的内容,把它封装到JavaBean中,方便使用。

传统的方法就是使用Properties类读取配置文件的Key和value,遍历它们,然后一一对应的封装到JavaBean中。

这时可以使用一个注解@ConfigurationProperties(prefix = “(前缀)”)

prefix是前缀

具体的使用步骤:

首先新建Car类,为他加入get/set方法还有tostring方法,有参无参构造方法等

使用@Component注解来注册到IOC容器中

@ConfigurationProperties(prefix = “mycar”)//读取properties文件中前缀为mycar的方法

注意:properties文件中的前缀必须全小写,不能使用驼峰写法

package com.kang.start.pojo;import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;@Component
@ConfigurationProperties(prefix = "mycar")
public class Car {public String brand;public Integer pirce;@Overridepublic String toString() {return "Car{" +"brand='" + brand + '\'' +", pirce=" + pirce +'}';}public String getBrand() {return brand;}public void setBrand(String brand) {this.brand = brand;}public Integer getPirce() {return pirce;}public void setPirce(Integer pirce) {this.pirce = pirce;}public Car() {}public Car(String brand, Integer pirce) {this.brand = brand;this.pirce = pirce;}
}

properties文件:

mycar.brand=baoma
mycar.pirce=10000

在Controller类中用@Autowried注解来吧IOC容器中的car类拽下来

@RestController
public class myConfig {@AutowiredCar car;@RequestMapping("/car")public Car car(){return car;}
}

访问这个页面

image-20250128092016762

@EnableConfigurationProperties注解

当然,我们还要考虑一种情况,就是这个组件如果不是我们自定义的我们要把它注册到IOC容器中怎么办呐?我们也不能在人家的源文件中添加@Component注解

这个时候,我们可以在配置类当中使用这个注解

@EnableConfigurationProperties(类名.class)

代替@Component注解;

主函数

@EnableAutoConfiguration注解

查看他的源文件里面有两个核心的注解

@AutoConfigurationPackage
@Import({AutoConfigurationImportSelector.class})
public @interface EnableAutoConfiguration {
@AutoConfigurationPackage注解

他的源码:

@Import({Registrar.class})//给容器导入组件
public @interface AutoConfigurationPackage {

其中导入组件的时候用的是Registrar来导入一系列组件

image-20250128094347691

所以说@EnableAutoConfiguration注解的一个作用就是导入指定包下的所有组件

具体来说就是main程序所在包下的所有组件

@Import({AutoConfigurationImportSelector.class})

@EnableAutoConfiguration还有一个重要的注解

@Import({AutoConfigurationImportSelector.class})

这个注解,先查看AutoConfigurationImportSelector这个方法,他是一个批处理方法。

其中有一个selectImports。

image-20250128095154097

研究一下getAutoConfigurationEntry(annotationMetadata)这个方法

他就是给IOC容器中批量导入组件,我们来Debug一下

image-20250128095934198

getAutoConfigurationEntry(annotationMetadata)这个方法就是调用

List<String> configurations = this.getCandidateConfigurations(annotationMetadata, attributes);

这个方法,获取所有要导入容器中的类。

此外还有一个重要的工厂方法;

protected List<AutoConfigurationImportFilter> getAutoConfigurationImportFilters() {return SpringFactoriesLoader.loadFactories(AutoConfigurationImportFilter.class, this.beanClassLoader);
}

利用工厂方法加载。

SpringFactoriesLoader方法

image-20250128213934438

默认他会扫描这个位置META-INF/spring.factories

在我们的自动装配核心类包spring-boot-autoconfigure-3.4.2.jar中

image-20250128214343134

说明这个文件里面声明了启动springBoot时要注册的所有配置类

按需开启

虽然所有的配置文件会全部配置,但是真正使用的时候只会按需配置。

比如说我们随便打开一个包

image-20250128223723179

条件配置,只有配置了指定的类才会继续下面的配置。最终会按照条件配置规则,按需装配

自动装配流程

条件装配流程

首先阅读一下aop类的源码

image-20250128224845584

image-20250128225040717

由于这个配置要求有Advice类,所以暂且将其称之为复杂配置。

image-20250128225251756

将这个要求不高的称之为简单配置。下面的ClassProxyingConfiguration就是对aop的配置。

修改默认配置

看一下dipatcherServlet的配置类DispatcherServletAutoConfiguration

位置:org\springframework\boot\autoconfigure\web\servlet\DispatcherServletAutoConfiguration.class

最下面有一个有趣的方法,文件上传解析器

@Bean
@ConditionalOnBean({MultipartResolver.class})//检测容器中是否有MultipartResolver类
@ConditionalOnMissingBean(name = {"multipartResolver"}//如果这个类的名字不是multipartResolver
)
public MultipartResolver multipartResolver(MultipartResolver resolver) {return resolver;//修正并返回正确的解析器
}

相关文章:

(2)SpringBoot自动装配原理简介

SpringBoot自动装配 这里写目录标题 SpringBoot自动装配启动器主程序自定义扫描包SpringBootApplicationSpringBootConfigurationEnableAutoConfigurationAutoConfigurationPackageImport({AutoConfigurationImportSelector.class})选择器AutoConfigurationEntrygetCandidateCo…...

Rust:Rhai脚本编程示例

当然&#xff0c;以下是一个简单的Rhai脚本编程示例&#xff0c;展示了如何在Rust中使用Rhai执行脚本。 首先&#xff0c;你需要确保你的Rust项目中包含了rhai库。你可以在你的Cargo.toml文件中添加以下依赖项&#xff1a; [dependencies] rhai "0.19" # 请检查最…...

深入理解文件描述符

问题 文件描述符只是一个整数值&#xff0c;那么系统是如何利用这个整数值来完成文件读写的呢&#xff1f; 什么是文件系统&#xff1f; 计算机中用于组织、存储和管理文件的数据结构集合 管理磁盘或其他存储介质上的空间 (将存储介质分块管理)保证文件数据不被破坏&#xf…...

使用CSS实现一个加载的进度条

文章目录 使用CSS实现一个加载的进度条一、引言二、步骤一&#xff1a;HTML结构与CSS基础样式1、HTML结构2、CSS基础样式 三、步骤二&#xff1a;添加动画效果1、使用CSS动画2、结合JavaScript控制动画 四、使用示例五、总结 使用CSS实现一个加载的进度条 一、引言 在现代网页…...

SQL 指南

SQL 指南 引言 SQL(Structured Query Language,结构化查询语言)是一种用于管理关系数据库系统的标准计算机语言。自1970年代问世以来,SQL已经成为了数据库管理和数据操作的事实标准。本文旨在为初学者和有经验的数据库用户提供一个全面的SQL指南,涵盖SQL的基础知识、高级…...

sqlzoo答案4:SELECT within SELECT Tutorial

sql练习&#xff1a;SELECT within SELECT Tutorial - SQLZoo world表&#xff1a; namecontinentareapopulationgdpAfghanistanAsia6522302550010020343000000AlbaniaEurope28748283174112960000000AlgeriaAfrica238174137100000188681000000AndorraEurope46878115371200000…...

斐波那契数(信息学奥赛一本通-1071)

【题目描述】 菲波那契数列是指这样的数列: 数列的第一个和第二个数都为1&#xff0c;接下来每个数都等于前面2个数之和。给出一个正整数k&#xff0c;要求菲波那契数列中第k个数是多少。 【输入】 输入一行&#xff0c;包含一个正整数k。&#xff08;1 ≤ k ≤ 46&#xff09;…...

数据结构与算法再探(六)动态规划

目录 动态规划 (Dynamic Programming, DP) 动态规划的基本思想 动态规划的核心概念 动态规划的实现步骤 动态规划实例 1、爬楼梯 c 递归&#xff08;超时&#xff09;需要使用记忆化递归 循环 2、打家劫舍 3、最小路径和 4、完全平方数 5、最长公共子序列 6、0-1背…...

ECMAScript--promise的使用

​ 一、Promise的简介 Promise是一个代理&#xff0c;它所代表的值在创建时并不一定是已知的。借助Promise&#xff0c;我们能够将处理程序与异步操作最终的成功值或者失败原因关联起来。这一特性使得异步方法可以像同步方法那样返回值&#xff0c;不同之处在于异步方法不会立…...

微服务入门(go)

微服务入门&#xff08;go&#xff09; 和单体服务对比&#xff1a;里面的服务仅仅用于某个特定的业务 一、领域驱动设计&#xff08;DDD&#xff09; 基本概念 领域和子域 领域&#xff1a;有范围的界限&#xff08;边界&#xff09; 子域&#xff1a;划分的小范围 核心域…...

【自学笔记】计算机网络的重点知识点-持续更新

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 计算机网络重点知识点一、计算机网络概述二、网络分类三、网络性能指标四、网络协议与体系结构五、数据交换方式六、物理层与数据链路层七、网络层与运输层八、应用…...

leetcode——二叉树的中序遍历(java)

给定一个二叉树的根节点 root &#xff0c;返回 它的 中序 遍历 。 示例 1&#xff1a; 输入&#xff1a;root [1,null,2,3] 输出&#xff1a;[1,3,2] 示例 2&#xff1a; 输入&#xff1a;root [] 输出&#xff1a;[] 示例 3&#xff1a; 输入&#xff1a;root [1] 输出…...

neo4j-community-5.26.0 install in window10

在住处电脑重新配置一下neo4j, 1.先至官方下载 Neo4j Desktop Download | Free Graph Database Download Neo4j Deployment Center - Graph Database & Analytics 2.配置java jdk jdk 21 官网下载 Java Downloads | Oracle 中国 path: 4.查看java -version 版本 5.n…...

物联网智能项目之——智能家居项目的实现!

成长路上不孤单&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a; 【14后&#x1f60a;///计算机爱好者&#x1f60a;///持续分享所学&#x1f60a;///如有需要欢迎收藏转发///&#x1f60a;】 今日分享关于物联网智能项目之——智能家居项目…...

基于SpringBoot的假期周边游平台的设计与实现(源码+SQL脚本+LW+部署讲解等)

专注于大学生项目实战开发,讲解,毕业答疑辅导&#xff0c;欢迎高校老师/同行前辈交流合作✌。 技术范围&#xff1a;SpringBoot、Vue、SSM、HLMT、小程序、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容&#xff1a;…...

JavaScript_03 超简计算器

版本一: <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>计算器</title><script type"text/javascript">function add(){let num1 document.getElementById("number1&qu…...

【重生之我在学习C语言指针详解】

目录 ​编辑 --------------------------------------begin---------------------------------------- 引言 一、指针基础 1.1 内存地址 1.2 指针变量 1.3 指针声明 1.4 取地址运算符 & 1.5 解引用运算符 *** 二、指针运算 2.1 指针加减运算 2.2 指针关系运算 三…...

深度学习每周学习总结R5(LSTM-实现糖尿病探索与预测-模型优化)

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客R7中的内容&#xff0c;为了便于自己整理总结起名为R5&#x1f356; 原作者&#xff1a;K同学啊 | 接辅导、项目定制 目录 0. 总结优化细节&#xff08;目前只采用了1、2两种方式&#xff09;1. L2 正则…...

单元测试在复杂业务逻辑开发中的重要性与实践

背景 以前编写程序时&#xff0c;我并没有养成大量撰写单元测试的习惯&#xff0c;尤其是在写偏向业务代码的情况下&#xff0c;写的单元测试很少&#xff0c;只有在封装一些公共方法的时候才会写一些测试用例。 然而&#xff0c;最近我在开发的一个业务时&#xff0c;深刻地…...

Kubernetes 环境中的自动化运维实战指南

Kubernetes 作为容器编排领域的领导者,已经成为云原生应用的核心基础设施。然而,随着集群规模的扩大和应用的复杂化,手动运维 Kubernetes 集群变得愈发困难。自动化运维成为提升效率、保障系统稳定性的关键。本文将详细介绍如何在 Kubernetes 环境中实施自动化运维,涵盖工具…...

Linux 如何使用fdisk进行磁盘相关的操作

简介 fdisk 命令是 Linux 中用于管理磁盘分区的强大文本实用程序。它可以创建、删除、调整大小和修改硬盘上的分区。 基本语法 fdisk [options] <device> <device>&#xff1a;要管理的磁盘&#xff0c;例如 /dev/sda、/dev/nvme0n1 或 /dev/vda 示例用法 列…...

嵌入式Linux:如何监视子进程

目录 1、wait()函数 2、waitpid()函数 3、SIGCHLD信号 在嵌入式Linux系统中&#xff0c;父进程通常需要创建子进程来执行特定任务&#xff0c;例如处理网络请求、执行计算任务等。监视子进程的状态不仅可以确保资源的合理利用&#xff0c;还能防止僵尸进程的产生&#xff0c…...

【信息系统项目管理师-选择真题】2010上半年综合知识答案和详解

更多内容请见: 备考信息系统项目管理师-专栏介绍和目录 文章目录 【第1~2题】【第3题】【第4题】【第5题】【第6题】【第7题】【第8题】【第9题】【第10题】【第11题】【第12题】【第13题】【第14题】【第15题】【第16题】【第17题】【第18题】【第19题】【第20题】【第21题】…...

工作总结:压测篇

前言 压测是测试需要会的一项技能&#xff0c;作为开发&#xff0c;有点时候也要会一点压测。也是被逼着现学现卖的。 一、压测是什么&#xff0c;以及压测工具的选择 压测&#xff0c;即压力测试&#xff0c;是一种性能测试手段&#xff0c;通过模拟大量用户同时访问系统&am…...

doris:STRUCT

STRUCT<field_name:field_type [COMMENT comment_string], ... > 表示由多个 Field 组成的结构体&#xff0c;也可被理解为多个列的集合。 不能作为 Key 使用&#xff0c;目前 STRUCT 仅支持在 Duplicate 模型的表中使用。一个 Struct 中的 Field 的名字和数量固定&…...

二叉树介绍

一.树的概念 树的图&#xff1a; 1.结点的度&#xff1a;一个结点含有子树的个数称为该结点的度&#xff1b; 如上图&#xff1a;A的度为6 2.树的度&#xff1a;一棵树中&#xff0c;所有结点度的最大值称为树的度&#xff1b; 如上图&#xff1a;树的度为6 3.叶子结点或终…...

通过Ngrok实现内网穿透助力远程开发

在现代软件开发和网络应用的环境下&#xff0c;开发人员常常需要在本地搭建服务器进行调试、测试或演示。然而&#xff0c;传统的端口映射&#xff08;如使用 NAT 或 SSH 隧道&#xff09;配置繁琐&#xff0c;且并非所有环境都允许直接暴露本地服务。ngrok 作为一款强大的隧道…...

DeepSeek-R1:通过强化学习激励大型语言模型(LLMs)的推理能力

摘要 我们推出了第一代推理模型&#xff1a;DeepSeek-R1-Zero和DeepSeek-R1。DeepSeek-R1-Zero是一个未经监督微调&#xff08;SFT&#xff09;作为初步步骤&#xff0c;而是通过大规模强化学习&#xff08;RL&#xff09;训练的模型&#xff0c;展现出卓越的推理能力。通过强…...

Node.js基础

浏览器知识 浏览器 个浏览器都内置了DOM、BOM等API函数&#xff0c;供浏览器中的Javascript调用。 每个浏览器都有对应的JavaScript解析引擎。 浏览器中的JavaScript环境 V8引擎负责解析和执行JavaScript代码 内置API是由运行环境提供的特殊接口&#xff0c;只能在所属的运…...

DeepSeek R1:中国AI黑马的崛起与挑战

在人工智能&#xff08;AI&#xff09;领域&#xff0c;大型语言模型&#xff08;LLMs&#xff09;正以迅猛之势重塑世界&#xff0c;其发展速度和影响力令人瞩目。近期&#xff0c;中国DeepSeek公司发布的DeepSeek R1模型&#xff0c;宛如一颗璀璨新星&#xff0c;凭借卓越的推…...

【JavaEE】_MVC架构与三层架构

目录 1. MVC架构 2. 三层架构 3. MVC架构与三层架构的对比 3.1 MVC与三层架构的对比 3.2 MVC与三层架构的共性 1. MVC架构 在前文已介绍关于SpringMAC的设计模式&#xff0c;详见下文&#xff1a; 【JavaEE】_Spring Web MVC简介-CSDN博客文章浏览阅读967次&#xff0c;点…...

对比DeepSeek、ChatGPT和Kimi的学术写作摘要能力

摘要 摘要是文章的精华&#xff0c;通常在200-250词左右。要包括研究的目的、方法、结果和结论。让AI工具作为某领域内资深的研究专家&#xff0c;编写摘要需要言简意赅&#xff0c;直接概括论文的核心&#xff0c;为读者提供快速了解的窗口。 下面我们使用DeepSeek、ChatGPT…...

ts 进阶

吴悠讲编程 : 20分钟TypeScript进阶&#xff01;无废话快速提升水平 前端速看 https://www.bilibili.com/video/BV1q64y1j7aH...

Kubernetes(一)

Kubernetes&#xff08;简称K8s&#xff09;是一个开源的容器编排平台&#xff0c;已经成为现代云原生应用的核心技术&#xff0c;主要应用于对容器化应用程序的自动化部署、扩展以及管理。k8s配备了一组核心组件以及一系列功能&#xff0c;这些组件能够实现容器的调度、负载均…...

Python里的小整数问题挺有意思的

简单来说&#xff0c;Python为了优化性能&#xff0c;会把一些常用的整数&#xff08;通常是-5到256&#xff09;提前创建好&#xff0c;放到一个“缓存池”里。这样&#xff0c;当你用到这些小整数时&#xff0c;Python就不用每次都重新创建对象了&#xff0c;直接从缓存池里拿…...

基于 Jenkins 的测试报告获取与处理并写入 Jira Wiki 的技术总结

title: 基于 Jenkins 的测试报告获取与处理并写入 Jira Wiki 的技术总结 tags: - jenkins - python categories: - jenkins在软件开发的持续集成与持续交付&#xff08;CI/CD&#xff09;流程里&#xff0c;及时、准确地获取并分析测试报告对保障软件质量至关重要。本文将详细…...

java.util.Random类(详细案例拆解)(已完结)

前言&#xff1a; 小编打算近期更俩三期类的专栏&#xff0c;一些常用的专集类&#xff0c;给大家分好类别总结和详细的代码举例解释。 今天是除夕&#xff0c;小编先祝贺大家除夕快乐啦&#xff01;&#xff01; 今天是第六个 java.lang.Math 包中的 java.util.Random类 我…...

CMake常用命令指南(CMakeList.txt)

CMakeList从入门到精通的文章有很多不再赘述&#xff08; 此处附带一篇优秀的博文链接&#xff1a;一个简单例子&#xff0c;完全入门CMake语法与CMakeList编写 &#xff09;。 本文主要列举 CMake 中常用命令的详细说明、优缺点分析以及推荐做法&#xff0c;以更好地理解和灵…...

Mybatis是如何进行分页的?

大家好&#xff0c;我是锋哥。今天分享关于【Mybatis是如何进行分页的&#xff1f;】面试题。希望对大家有帮助&#xff1b; Mybatis是如何进行分页的&#xff1f; 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 MyBatis 实现分页的方式有很多种&#xff0c;最常见…...

推动知识共享的在线知识库实施与优化指南

内容概要 在当今迅速发展的数字化时代&#xff0c;在线知识库的实施显得尤为重要。它不仅为企业提供了高效的信息存储与共享平台&#xff0c;还能够有效促进团队成员之间的协作与知识传递。通过集中管理企业内的各类知识资源&#xff0c;在线知识库帮助员工快速查找所需信息&a…...

【最后203篇系列】007 使用APS搭建本地定时任务

说明 最大的好处是方便。 其实所有任务的源头&#xff0c;应该都是通过定时的方式&#xff0c;在每个时隙发起轮询。当然在任务的后续传递中&#xff0c;可以通过CallBack或者WebHook的方式&#xff0c;以事件的形态进行。这样可以避免长任务执行的过程中进行等待和轮询。 总结…...

为AI聊天工具添加一个知识系统 之78 详细设计之19 正则表达式 之6

本文要点 要点 本项目设计的正则表达式 是一个 动态正则匹配框架。它是一个谓词系统&#xff1a;谓词 是运动&#xff0c;主语是“维度”&#xff0c;表语是 语言处理。主语的一个 双动结构。 Reg三大功能 语法验证、语义检查和 语用检验&#xff0c;三者 &#xff1a;语义约…...

三天急速通关JavaWeb基础知识:Day 1 后端基础知识

三天急速通关JavaWeb基础知识&#xff1a;Day 1 后端基础知识 0 文章说明1 Http1.1 介绍1.2 通信过程1.3 报文 Message1.3.1 请求报文 Request Message1.3.2 响应报文 Response Message 2 XML2.1 介绍2.2 利用Java解析XML 3 Tomcat3.1 介绍3.2 Tomcat的安装与配置3.3 Tomcat的项…...

代理模式 -- 学习笔记

代理模式学习笔记 什么是代理&#xff1f; 代理是一种设计模式&#xff0c;用户可以通过代理操作&#xff0c;而真正去进行处理的是我们的目标对象&#xff0c;代理可以在方法增强&#xff08;如&#xff1a;记录日志&#xff0c;添加事务&#xff0c;监控等&#xff09; 拿一…...

前端-Rollup

Rollup 是一个用于 JavaScript 的模块打包工具&#xff0c;它将小的代码片段编译成更大、更复杂的代码&#xff0c;例如库或应用程序。它使用 JavaScript 的 ES6 版本中包含的新标准化代码模块格式&#xff0c;而不是以前的 CommonJS 和 AMD 等特殊解决方案。ES 模块允许你自由…...

EtherCAT主站IGH-- 21 -- IGH之fsm_reboot.h/c文件解析

EtherCAT主站IGH-- 21 -- IGH之fsm_reboot.h/c文件解析 0 预览一 该文件功能`fsm_reboot.c` 文件功能函数预览二 函数功能介绍`fsm_reboot.c` 中主要函数的作用1. `ec_fsm_reboot_init`2. `ec_fsm_reboot_clear`3. `ec_fsm_reboot_single`4. `ec_fsm_reboot_all`5. `ec_fsm_reb…...

【NLP251】NLP RNN 系列网络

NLP251 系列主要记录从NLP基础网络结构到知识图谱的学习 &#xff11;.原理及网络结构 &#xff11;.&#xff11;&#xff32;&#xff2e;&#xff2e; 在Yoshua Bengio论文中( http://proceedings.mlr.press/v28/pascanu13.pdf )证明了梯度求导的一部分环节是一个指数模型…...

数据分析系列--④RapidMiner进行关联分析(案例)

一、核心概念 1.1项集&#xff08;Itemset&#xff09; 1.2规则&#xff08;Rule&#xff09; 1.3支持度&#xff08;Support&#xff09; 1.3.1 支持度的定义 1.3.2 支持度的意义 1.3.3 支持度的应用 1.3.4 支持度的示例 1.3.5 支持度的调整 1.3.6 支持度与其他指标的…...

深度学习:基于MindNLP的RAG应用开发

什么是RAG&#xff1f; RAG&#xff08;Retrieval-Augmented Generation&#xff0c;检索增强生成&#xff09; 是一种结合检索&#xff08;Retrieval&#xff09;和生成&#xff08;Generation&#xff09;的技术&#xff0c;旨在提升大语言模型&#xff08;LLM&#xff09;生…...

Hive安装教程

Hive安装教程 文章目录 Hive安装教程写在前面安装下载安装部署安装Hive启动并使用Hive MySQL安装检查当前系统是否安装过MySQL安装初始化数据库 Hive元数据配置到MySQL拷贝驱动配置Metastore到MySQL再次启动Hive 写在前面 Linux版本&#xff1a;CentOS7.5Hive版本&#xff1a;…...