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

Spring依赖注入方式

 写在前面:大家好!我是晴空๓。如果博客中有不足或者的错误的地方欢迎在评论区或者私信我指正,感谢大家的不吝赐教。我的唯一博客更新地址是:https://ac-fun.blog.csdn.net/。非常感谢大家的支持。一起加油,冲鸭!
用知识改变命运,用知识成就未来!加油 (ง •̀o•́)ง (ง •̀o•́)ง

文章目录

  • 前言
  • 依赖注入方式
    • 基于构造法方法的注入
    • 基于Setter方法的注入
    • 基于字段注入
    • 基于方法注入
  • 配置方式
    • 示例代码
    • 基于XML文件的配置注入
      • pom依赖
      • 相关标签
        • bean标签
        • constructor-arg标签
        • property标签
      • XML实现构造器注入
      • XML实现Setter方法注入
    • 基于注解的配置注入
      • 将一个类声明为Bean的注解
      • 可注入依赖的注解
      • 基于XML和注解混合方式
    • 基于Java类的配置注入
        • @ComponentScan
        • @Bean

前言

Spring 框架对于 Java 服务端开发无疑是一个举足轻重的存在,它以简洁、高效、灵活的特性为我们开发提供了强大的支持,极大的提高了我们的开发效率和代码质量。Spring 解决了一个非常重要的问题,它可以通过 XML 或者 注解 来管理对象之间的依赖关系,也就是 Spring 的依赖注入机制。

依赖注入(Dependency Injection,DI) 作为 Spring 核心理念之一,贯穿于整个框架的使用之中。通过依赖注入Spring容器在创建一个对象时,会自动将这个对象的依赖注入进去,就不需要程序员主动通过 new对象 的方式进行对象创建。Spring 通过依赖注入机制打破了传统编程中对象之间紧密耦合的局面,让各个组件能够更加独立、灵活地进行开发、测试和维护,为构建复杂而稳定的软件系统奠定了坚实的基础。Spring 框架提供了多种依赖注入方式,本文主要介绍一下 Spring 框架中各种依赖注入的方式。

依赖注入方式

Spring 主要有三种常见的注入方式,分别是基于构造方法的注入、基于Setter方法的注入、基于字段注入。还有不经常使用的基于方法注入、接口回调注入
依赖注入示意图

基于构造法方法的注入

 所谓基于构造方法注入,就是通过构造方法将依赖项传递给对象。在对象实例化时,Spring IoC 容器会根据构造方法的参数类型,从容器中查找并注入匹配的依赖项。

public class MyService {  private final MyDependency myDependency;  @Autowired  public MyService(MyDependency myDependency) {  this.myDependency = myDependency;  }  
}  

 相比于其他注入方式,Spring 官方更推荐构造函数注入。官方文档说明如下(https://docs.spring.io/spring-framework/reference/core/beans/dependencies/factory-collaborators.html#beans-setter-injection):
构造器还是Setter
官方推荐使用构造器注入的原因主要有以下几点:

  1. 依赖完整性:构造器注入可以确保在对象创建时,所有必需的依赖项都已经被注入,从而避免空指针异常。
  2. 实现不可变对象:构造器注入可以将对象实现为不可变对象,即对象的状态在创建后不能被修改。不可变对象在多线程环境中更安全,因为它们的状态不会被改变
  3. 初始化保证:通过构造器注入的组件总是以完全初始化的状态返回给客户端(调用方)代码。组件在使用前已完全初始化,减少了潜在的错误。
  4. 避免过多的构造器参数:构造器注入鼓励将类的设计保持简洁,避免过多的依赖项。如果一个类有过多的构造器参数,这通常是一个糟糕的设计,表明该类承担了过多的职责,应该进行重构。

基于Setter方法的注入

 通过类的 Setter 方法来注入依赖项。适用于可选依赖或易于变更的配置属性的场景,因为对象可以先创建一个默认状态,然后再通过 Setter 方法补充注入依赖。基于 Setter 方法注入的一个好处是,Setter 方法使得该类的对象便于以后重新配置或重新注入。

public class MyService {  private MyDependency myDependency;  @Autowired  public void setMyDependency(MyDependency myDependency) {  this.myDependency = myDependency;  }  
}

基于字段注入

 基于字段注入直接通过注解(@Autowired、@Resource、@Inject)将依赖项注入到目标类的字段中。这是最简洁的方式,但通常不推荐使用。

public class MyService {  @Autowired  private MyDependency myDependency;  
}

基于方法注入

 通过普通方法(非Setter方法)注入依赖项。这种方式较为灵活,但使用较少。

public class MyService {  public void performAction(@Autowired MyDependency myDependency) {  myDependency.doSomething();  }  
}

配置方式

 以上这些注入方式主要通过三种方式进行配置,分别是基于XML文件的配置、基于注解的配置和基于Java类的配置。其中基于XML文件的配置Spring 早期的配置方式,现在使用的比较少。目前我们常用的配置方式主要是后两种。但是第一种方式也是需要了解的,如果看一些老项目的话还是需要掌握一下。

示例代码

 为了方便展示写了一个简单的计算器,该计算器只实现了加减乘除操作,我们需要在计算器的 Controller 类中注入加减乘除服务的实现类 ServiceImpl
目录结构

// CalculatorApplication类
package com.qingkong.application;import com.qingkong.calculator.CalculatorController;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class CalculatorApplication {public static void main(String[] args) {// 加载Spring的配置文件ApplicationContext context = new ClassPathXmlApplicationContext("beans.xml");// 获取 CalculatorController BeanCalculatorController calculatorController = context.getBean(CalculatorController.class);// 测试计算器的功能System.out.println(calculatorController.add(1, 2));}
}---
// CalculatorService 接口
package com.qingkong.service;public interface CalculatorService {double add(double a, double b);double subtract(double a, double b);double multiply(double a, double b);double divide(double a, double b);
}---
// CalculatorService 接口实现类
package com.qingkong.service.impl;import com.qingkong.service.CalculatorService;public class CalculatorServiceImpl implements CalculatorService {public CalculatorServiceImpl() {System.out.println("CalculatorServiceImpl无参构造方法被调用了");}@Overridepublic double add(double a, double b) {return a + b;}@Overridepublic double subtract(double a, double b) {return a - b;}@Overridepublic double multiply(double a, double b) {return a * b;}@Overridepublic double divide(double a, double b) {if (b == 0) {throw new IllegalArgumentException("不能除以0!");}return a / b;}
}

基于XML文件的配置注入

pom依赖

 要想实现 Spring 的依赖注入功能,需要引入 spring-context 依赖。spring-context 模块是 Spring 框架的核心模块之一,它提供了支持 Spring 应用上下文和事件驱动模型的功能。它构建在 spring-corespring-beans 模块之上,提供了以下功能:

  • 依赖注入(DI):支持通过 XML 配置、注解或 Java 配置进行依赖注入。
  • 应用上下文(ApplicationContext):提供了更高级的上下文接口,如 ClassPathXmlApplicationContextFileSystemXmlApplicationContext,用于加载配置文件和管理 Bean
  • 事件支持:支持事件发布和监听。

 我们只在 pom.xml 中引入 spring-context 依赖,Maven 会根据 依赖传递 自动将 spring-core、spring-bean、spring-aop等spring-context依赖的其他 Spring 模块引入。这些模块是 spring 框架的核心模块,真实的开发场景下还会引入其他模块。

<dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.3.30</version>
</dependency>

依赖

相关标签

bean标签

 在 XML 中我们可以通过 <bean> 标签来配置一个bean,该标签主要的元素如下所示:

属性作用
idBean 的唯一标识符,用于在 Spring 容器中引用该 Bean
classBean 的全限定类名
scope定义 Bean 的作用域(如 singleton、prototype 等)
autowire指定自动装配的方式(如 byName、byType 等)
factory-bean指定一个工厂 Bean,用于创建当前 Bean
factory-method指定工厂 Bean 中用于创建当前 Bean 的方法,与 factory-bean 配合使用
parent指定当前 Bean 的父 Bean
lazy-init指定是否延迟初始化该 Bean
depends-on指定该 Bean 依赖的其他 Bean
primary标记当前 Bean 为优先选择的 Bean
init-method指定 Bean 初始化时执行的方法
destroy-method指定 Bean 销毁时执行的方法
constructor-arg标签

XML 配置文件使用 <constructor-arg/> 标签传入构造方法所需要的内容。该标签主要的属性如下:

属性作用
ref传给构造方法参数的Bean ID
value传给构造方法参数的值
type构造方法参数对应的类型
index构造方法参数对应的位置,从0开始计算
name构造方法参数对应的名称
property标签

 使用 <property/> 可以为 Bean 的属性赋值或注入其他 Bean。该标签主要的元素如下:

属性作用
name指定要设置的属性名称
value指定要注入的属性值
ref引用另一个 Bean 的 Bean ID

XML实现构造器注入

 对于 CalculatorController 类,先生成该类的构造方法,然后将其依赖的 CalculatorService 类作为构造方法的参数注入。完成之后在 XML 文件中进行配置,具体实现如下:

CalculatorController类:

public class CalculatorController {private final CalculatorService calculatorService;// 构造器注入public CalculatorController(CalculatorService calculatorService) {System.out.println("开始进行构造器注入");this.calculatorService = calculatorService;}public double add(double a, double b) {return calculatorService.add(a, b);}public double subtract(double a, double b) {return calculatorService.subtract(a, b);}public double multiply(double a, double b) {return calculatorService.multiply(a, b);}public double divide(double a, double b) {return calculatorService.divide(a, b);}
}

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/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd"><!-- 定义 CalculatorService 的 Bean --><bean id="calculatorService" class="com.qingkong.service.impl.CalculatorServiceImpl"/><!-- 定义 CalculatorController 的 Bean,使用构造器注入 --><bean id="calculatorController" class="com.qingkong.calculator.CalculatorController" ><constructor-arg ref="calculatorService"/></bean></beans>

XML实现Setter方法注入

 首先在 CalculatorController 类中设置 calculatorService 的类型的属性,然后生成 Set 方法。完成之后在 XML 文件中进行配置,具体实现如下:

CalculatorController类:

public class CalculatorController {private CalculatorService calculatorService;// Set方法public void setCalculatorService(CalculatorService calculatorService) {System.out.println("开始进行Setter方法注入");this.calculatorService = calculatorService;}public double add(double a, double b) {return calculatorService.add(a, b);}public double subtract(double a, double b) {return calculatorService.subtract(a, b);}public double multiply(double a, double b) {return calculatorService.multiply(a, b);}public double divide(double a, double b) {return calculatorService.divide(a, b);}
}

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/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd"><!-- 定义 CalculatorService 的 Bean --><bean id="calculatorService" class="com.qingkong.service.impl.CalculatorServiceImpl"/><!-- 定义 CalculatorController 的 Bean,使用Setter方法注入 --><bean id="calculatorController" class="com.qingkong.calculator.CalculatorController" ><!-- name属性的值对应 calculatorController 方法中相关属性的名称 --><property name="calculatorService" ref="calculatorService"/></bean></beans>

基于注解的配置注入

 使用注解注入有两种方式,分别是基于XML和注解混合方式纯注解方式。第一种方式需要在 XML 文件中配置 context:component-scan 标签,而基于纯注解方式则不需要进行任何 XML 配置,只需要在配置类中加入 @ComponentScan 注解并执行扫描包路径即可。

将一个类声明为Bean的注解

 在 XML配置注入 中我们通过 <bean/> 配置一个 Bean,而在基于注解的配置时我们只需要在类上面添加如下四个注解中的任意一个都能让 Spring 容器把他们配置为 Bean

注解说明
@Component将类标识为普通的Bean
@Service用于标识服务层的类
@Controller用于标识控制器层(Controller)的类(后来针对REST服务又增加了一个@RestController注解)
@Repository用于标识数据访问层的类,与数据库进行交互

 这四个注解本质上没有区别,而且后面三个注解都是 @Component 注解的衍生注解,之所以这么做主要是为了在分层架构中提供更好的语义化支持和分层的明确性,提高代码的可读性和可维护性。

可注入依赖的注解

Spring 内置的 @Autowired 以及 JDK 内置的 @Resource@Inject 都可以用于注入 Bean。这里需要注意的是 @Autowired 默认的注入方式为 byType(根据类型进行匹配),如果一个接口存在多个实现类,Spring 会同时找到多个满足条件的选择,这种情况下,注入方式会变为 byName(根据名称进行匹配),这个名称通常就是类名(首字母小写)。

 如果一个接口有多个实现类一般建议使用 @Autowired@Qualifier 注解配合的方式来显式指定名称而不是依赖变量的名称来区分。@Qualifier 注解主要用来在依赖注入时消除歧义。当面对一个接口有多个实现类我们可以使用 @Qualifier(“类名”) 的方式使 Spring 在依赖注入时准确的找到依赖。

@Resource 默认注入方式为 byName。如果无法通过名称匹配到对应的 Bean 时,注入方式会变为 byType。 该注解 nametype 有两个重要的属性。如果仅指定 name 属性则注入方式为 byName,如果仅指定 type属性则注入方式为 byType,如果同时指定 nametype 属性(不建议这么做)则注入方式为byType + byName

基于XML和注解混合方式

CalculatorServiceImpl类

@Component
public class CalculatorServiceImpl implements CalculatorService {// 省略重复代码……
}

CalculatorController类

@Component
public class CalculatorController {@Autowiredprivate CalculatorService calculatorService;public double add(double a, double b) {return calculatorService.add(a, b);}public double subtract(double a, double b) {return calculatorService.subtract(a, b);}public double multiply(double a, double b) {return calculatorService.multiply(a, b);}public double divide(double a, double b) {return calculatorService.divide(a, b);}
}

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/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsd"><!-- 开启注解并扫描指定包中带有注解的类   --><context:component-scan base-package = "com.qingkong"/></beans>

基于Java类的配置注入

 从 Spring Framework 3.0 开始,我们可以使用 @Configuration 注解定义配置类,可以达到替换 XML 配置文件的效果。使用 @Configuration、@Bean、@ComponentScan 等一系列注解,基本可以满足日常开发所需。

我们只需要将原来的 XML 配置文件删除,再加上带有 @Configuration 注解的配置类即可。
目录结构

配置类代码:

@Configuration
@ComponentScan("com.qingkong")
public class Config {
}

 当使用时需要通过 AnnotationConfigApplicationContext 对象来加载我们定义的配置类。

// 加载Spring的配置类
ApplicationContext context = new AnnotationConfigApplicationContext(Config.class);
// 获取 CalculatorController Bean
CalculatorController calculatorController = context.getBean(CalculatorController.class);
@ComponentScan

@ComponentScan 注解指定了类扫描的包名,作用与 XML 配置文件中的 <context:component-scan/> 类似。如果配置类的 @ComponentScan 没有指定扫描的基础包路径或者类,那么默认从该配置类的包开始扫描(最好还是指定路径,防止漏包)。该注解的 includeFiltersexcludeFilters 属性可以用来指定包含和排除组件。官网中也给出了相应的示例:

@Configuration
@ComponentScan(basePackages = "org.example",includeFilters = @Filter(type = FilterType.REGEX, pattern = ".*Stub.*Repository"),excludeFilters = @Filter(Repository.class))
public class AppConfig {...
}

该配置类与以下 XML配置 等效:

<beans><context:component-scan base-package="org.example"><context:include-filter type="regex"expression=".*Stub.*Repository"/><context:exclude-filter type="annotation"expression="org.springframework.stereotype.Repository"/></context:component-scan>
</beans>
@Bean

 我们也可以在配置类将 @Bean 注解放在方法上面,这样方法的返回对象就会被当做容器的一个 Bean。默认情况下,Bean 名称与方法名称相同。官网给出了使用例子:

@Configuration
public class AppConfig {@Beanpublic TransferService transferService() {return new TransferServiceImpl();}
}

该配置与以下 XML 中的配置是等价的:

<beans><bean id="transferService" class="com.acme.TransferServiceImpl"/>
</beans>

 既然有了 @Component 等注解为什么还要用 @Bean 注解呢?@Component 注解作用于类,而 @Bean 注解作用于方法。当我们引用第三方库中的类需要装配到 Spring 容器时,只能用 @Bean 注解来实现,因为通常情况下我们是无法修改第三方类库的代码的。


  1. https://docs.spring.io/spring-framework/docs/5.2.x/spring-framework-reference/core.html#spring-core
  2. 《学透Spring 从入门到项目实战》
  3. JavaGuide

相关文章:

Spring依赖注入方式

写在前面&#xff1a;大家好&#xff01;我是晴空๓。如果博客中有不足或者的错误的地方欢迎在评论区或者私信我指正&#xff0c;感谢大家的不吝赐教。我的唯一博客更新地址是&#xff1a;https://ac-fun.blog.csdn.net/。非常感谢大家的支持。一起加油&#xff0c;冲鸭&#x…...

Photoshop自定义键盘快捷键

编辑 - 键盘快捷键 CtrlShiftAltK 把画笔工具改成Q , 橡皮擦改成W , 涂抹工具改成E , 增加和减小画笔大小A和S 偏好设置 - 透明度和色域 设置一样颜色 套索工具 可以自定义套选一片区域 Shiftf5 填充 CtrlU 可以改颜色/色相/饱和度 CtrlE 合并图层 CtrlShiftS 另存…...

解决VsCode的 Vetur 插件has no default export Vetur问题

文章目录 前言1.问题2. 原因3. 解决其他 前言 提示&#xff1a; 1.问题 Cannot find module ‘ant-design-vue’. Did you mean to set the ‘moduleResolution’ option to ‘node’, or to add aliases to the ‘paths’ option? Module ‘“/xxx/xxx/xxx/xxx/xxx/src/vie…...

关于浏览器缓存的思考

问题情境 开发中要实现一个非原生pdf预览功能&#xff0c;pdf链接放在一个固定的后台地址&#xff0c;当重新上传pdf后&#xff0c;预览pdf仍然是上一次的pdf内容&#xff0c;没有更新为最新的内容。 查看接口返回状态码为 200 OK(from disk cache)&#xff0c; 表示此次pdf返回…...

Vue3+element-plus表单重置resetFields方法失效问题

遇到的其中一种情况&#xff1a; bug&#xff1a;在当前页面直接筛选重置&#xff0c;重置方法生效&#xff1b;但先筛选&#xff0c;再切换别的页面&#xff0c;再切回原页面重置&#xff0c;重置无效&#xff08;keep-alive的页面无此bug&#xff09; 原因&#xff1a; 1.Vue…...

解释和对比“application/octet-stream“与“application/x-protobuf“

介绍 在现代 Web 和分布式系统的开发中&#xff0c;数据的传输和交换格式扮演着关键角色。为了确保数据在不同系统之间的传输过程中保持一致性&#xff0c;MIME 类型&#xff08;Multipurpose Internet Mail Extensions&#xff09;被广泛应用于描述数据的格式和内容类型。在 …...

1158:求1+2+3+...

【题目描述】 用递归的方法求123……N123……N的值。 【输入】 输入N。 【输出】 输出和。 【输入样例】 5 【输出样例】 15 【解题思路】 递归 递归问题&#xff1a;求12…k的和递归关系&#xff1a;如果想求12…k的和&#xff0c;需要先求12…k-1的和&#xff0c;再加上…...

前端实现在PDF上添加标注(1)

前段时间接到一个需求&#xff0c;用户希望网页上预览PDF&#xff0c;同时能在PDF上添加文字&#xff0c;划线&#xff0c;箭头和用矩形框选的标注&#xff0c;另外还需要对已有的标注进行修改&#xff0c;删除。 期初在互联网上一通搜索&#xff0c;对这个需求来讲发现了两个问…...

螺旋矩阵 II

螺旋矩阵 II 一、题目描述 给定一个正整数 n&#xff0c;请你生成一个包含 1 到 n^2 所有元素的 n x n 正方形矩阵&#xff0c;元素顺序按顺时针的方式进行螺旋排列。 示例 1&#xff1a;输入&#xff1a;n 3 输出&#xff1a;[[1,2,3],[8,9,4],[7,6,5]]示例 2&#xff1a;…...

【愚公系列】《Python网络爬虫从入门到精通》001-初识网络爬虫

标题详情作者简介愚公搬代码头衔华为云特约编辑&#xff0c;华为云云享专家&#xff0c;华为开发者专家&#xff0c;华为产品云测专家&#xff0c;CSDN博客专家&#xff0c;CSDN商业化专家&#xff0c;阿里云专家博主&#xff0c;阿里云签约作者&#xff0c;腾讯云优秀博主&…...

【linux学习指南】模拟线程封装与智能指针shared_ptr

文章目录 &#x1f4dd;线程封装&#x1f309; Thread.hpp&#x1f309; Makefile &#x1f320;线程封装第一版&#x1f309; Makefile:&#x1f309;Main.cc&#x1f309; Thread.hpp: &#x1f320;线程封装第二版&#x1f309; Thread.hpp:&#x1f309; Main.cc &#x1f…...

10、Python面试题解析:解释reduce函数的工作原理

reduce 是 Python 中的一个高阶函数&#xff0c;位于 functools 模块中。它的作用是将一个可迭代对象&#xff08;如列表、元组等&#xff09;中的元素依次通过一个二元函数&#xff08;即接受两个参数的函数&#xff09;进行累积计算&#xff0c;最终返回一个单一的结果。 1.…...

【含开题报告+文档+PPT+源码】学术研究合作与科研项目管理应用的J2EE实施

开题报告 本研究构建了一套集注册登录、信息获取与科研项目管理于一体的综合型学术研究合作平台。系统用户通过注册登录后&#xff0c;能够便捷地接收到最新的系统公告和科研动态新闻&#xff0c;并能进一步点击查看详尽的新闻内容。在科研项目管理方面&#xff0c;系统提供强…...

MySQL主从复制过程,延迟高,解决应对策略

MySQL主从复制延迟高是常见的性能问题&#xff0c;通常由主库写入压力大、从库处理能力不足或配置不当导致。以下从原因定位、优化策略和高级解决方案三个维度提供系统性解决方法&#xff1a; 一、快速定位延迟原因 1. 查看主从同步状态 SHOW SLAVE STATUS\G关键字段&#xf…...

Deepseek模拟阿里面试——数据库

在模拟阿里面试时&#xff0c;数据库部分需要涵盖广泛的知识点&#xff0c;包括基础概念、事务管理、索引优化、数据库设计、高并发处理、分布式数据库等。以下是对这些问题的详细分析和解答&#xff1a; 事务的ACID特性是什么&#xff0c;如何保证&#xff1f; ACID特性&…...

大数据学习之SparkStreaming、PB级百战出行网约车项目一

一.SparkStreaming 163.SparkStreaming概述 Spark Streaming is an extension of the core Spark API that enables scalable, high-throughput, fault-tolerant stream processing of live data streams. Spark Streaming 是核心 Spark API 的扩展&#xff0c;支持实时数据…...

Java 高频面试闯关秘籍

目录 Java基础篇&#xff1a;涵盖OOP、多线程、集合等基础知识。Java高级篇&#xff1a;深入探讨HashMap、JVM、线程池等高级特性。Java框架篇&#xff1a;介绍Spring、SpringMVC、MyBatis等常用框架。Mysql数据库篇&#xff1a;包含SQL语句、事务、索引等数据库知识。分布式技…...

边缘计算网关驱动智慧煤矿智能升级——实时预警、低延时决策与数字孪生护航矿山安全高效运营

迈向智能化煤矿管理新时代 工业物联网和边缘计算技术的迅猛发展&#xff0c;煤矿安全生产与高效运营正迎来全新变革。传统煤矿监控模式由于现场环境复杂、数据采集和传输延时较高&#xff0c;已难以满足当下高标准的安全管理要求。为此&#xff0c;借助边缘计算网关的实时数据…...

Oracle认证大师(OCM)学习计划书

Oracle认证大师&#xff08;OCM&#xff09;学习计划书 一、学习目标 Oracle Certified Master&#xff08;OCM&#xff09;是Oracle官方认证体系中的最高级别认证&#xff0c;要求考生具备扎实的数据库管理技能、丰富的实战经验以及解决复杂问题的能力。本计划旨在通过系统化的…...

力扣 单词拆分

动态规划&#xff0c;字符串截取&#xff0c;可重复用&#xff0c;集合类。 题目 单词可以重复使用&#xff0c;一个单词可用多次&#xff0c;应该是比较灵活的组合形式了&#xff0c;可以想到用dp&#xff0c;遍历完单词后的状态的返回值。而这里的wordDict给出的是list&…...

【Axure高保真原型】引导弹窗

今天和大家中分享引导弹窗的原型模板&#xff0c;载入页面后&#xff0c;会显示引导弹窗&#xff0c;适用于引导用户使用页面&#xff0c;点击完成后&#xff0c;会显示下一个引导弹窗&#xff0c;直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…...

生成xcframework

打包 XCFramework 的方法 XCFramework 是苹果推出的一种多平台二进制分发格式&#xff0c;可以包含多个架构和平台的代码。打包 XCFramework 通常用于分发库或框架。 使用 Xcode 命令行工具打包 通过 xcodebuild 命令可以打包 XCFramework。确保项目已经配置好需要支持的平台…...

docker详细操作--未完待续

docker介绍 docker官网: Docker&#xff1a;加速容器应用程序开发 harbor官网&#xff1a;Harbor - Harbor 中文 使用docker加速器: Docker镜像极速下载服务 - 毫秒镜像 是什么 Docker 是一种开源的容器化平台&#xff0c;用于将应用程序及其依赖项&#xff08;如库、运行时环…...

Python:操作 Excel 折叠

💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 Python 操作 Excel 系列 读取单元格数据按行写入设置行高和列宽自动调整行高和列宽水平…...

系统设计 --- MongoDB亿级数据查询优化策略

系统设计 --- MongoDB亿级数据查询分表策略 背景Solution --- 分表 背景 使用audit log实现Audi Trail功能 Audit Trail范围: 六个月数据量: 每秒5-7条audi log&#xff0c;共计7千万 – 1亿条数据需要实现全文检索按照时间倒序因为license问题&#xff0c;不能使用ELK只能使用…...

ElasticSearch搜索引擎之倒排索引及其底层算法

文章目录 一、搜索引擎1、什么是搜索引擎?2、搜索引擎的分类3、常用的搜索引擎4、搜索引擎的特点二、倒排索引1、简介2、为什么倒排索引不用B+树1.创建时间长,文件大。2.其次,树深,IO次数可怕。3.索引可能会失效。4.精准度差。三. 倒排索引四、算法1、Term Index的算法2、 …...

【python异步多线程】异步多线程爬虫代码示例

claude生成的python多线程、异步代码示例&#xff0c;模拟20个网页的爬取&#xff0c;每个网页假设要0.5-2秒完成。 代码 Python多线程爬虫教程 核心概念 多线程&#xff1a;允许程序同时执行多个任务&#xff0c;提高IO密集型任务&#xff08;如网络请求&#xff09;的效率…...

零基础设计模式——行为型模式 - 责任链模式

第四部分&#xff1a;行为型模式 - 责任链模式 (Chain of Responsibility Pattern) 欢迎来到行为型模式的学习&#xff01;行为型模式关注对象之间的职责分配、算法封装和对象间的交互。我们将学习的第一个行为型模式是责任链模式。 核心思想&#xff1a;使多个对象都有机会处…...

Redis数据倾斜问题解决

Redis 数据倾斜问题解析与解决方案 什么是 Redis 数据倾斜 Redis 数据倾斜指的是在 Redis 集群中&#xff0c;部分节点存储的数据量或访问量远高于其他节点&#xff0c;导致这些节点负载过高&#xff0c;影响整体性能。 数据倾斜的主要表现 部分节点内存使用率远高于其他节…...

html-<abbr> 缩写或首字母缩略词

定义与作用 <abbr> 标签用于表示缩写或首字母缩略词&#xff0c;它可以帮助用户更好地理解缩写的含义&#xff0c;尤其是对于那些不熟悉该缩写的用户。 title 属性的内容提供了缩写的详细说明。当用户将鼠标悬停在缩写上时&#xff0c;会显示一个提示框。 示例&#x…...