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

Spring IoC DI

目录

一. IoC & DI 入门

1. 重谈Spring

2. 容器

3.  IoC

① 传统程序开发

② IoC 程序开发

③ IoC 的优势

 4. DI

3. IoC & DI 使用

二. IoC & DI 详解

1. Bean的存储

2. Bean的重命名 

3. 扫描路径 

三. DI 详解

1. 属性注入

2. 构造方法注入

3. Setter注入

 4. 三种注入方式的优缺点分析

(1) 属性注入

(2) 构造方法注入

(3) Setter注入


一. IoC & DI 入门

1. 重谈Spring

我们知道 Spring 是一个功能强大的开源框架. 这是从Spring 的用途和功能角度来谈的.
而从另一个角度来说, Spring就是一个包含了众多工具和方法的IoC容器.

2. 容器

什么是容器? --> 容器就是用来容纳某种物品的装置.

生活中的容器是用来容纳某种物品的装置. 在Java开发中, 也是类似的: 容器也是用来容纳某些东西的. 我们可以回想以前学过的容器:

  • 集合框架中: List, Map --> 用来存储数据的容器.
  • SpringMVC中: Tomcat --> 是一个 Servlet 容器, 也常被称为 Java Web 容器.           

3.  IoC

IoC 是Spring 的核心思想. 那么IoC究竟是什么呢?

其实前面我们已经使用过IoC, 在类上面加上 @RestController 和 @Controller 注解, 就是把这个类的对象交给Spring管理. 在Spring启动时, 就会自动加载该类.

所以说: 把对象交给Spring管理, 就是IoC思想. 

详细的说: IoC (Inversion Of Control) 即 "控制反转". 说Spring是一个IoC容器, 也就是说他是一个"控制反转"容器. 那么, 何为控制反转? --> 控制反转, 也就是对象的控制权反转. 在传统的开发中, 如果我们需要某个类的对象, 需要自己通过new来创建. 而使用Spring之后 则不需要再手动进行创建了. 我们把创建对象的任务交给容器, 程序中只需要进行依赖注入(DI "Dependency Injection") 就可以了. 这个容器就是IoC容器. Spring就是一个IoC容器.

  • 下面我们通过第一个例子来介绍一下何为IoC:

        假设我们现在要造一辆车: 先设计轮子(Tire), 然后根据轮子设计底盘(Bottom), 接着根据底盘设计车身(Framework), 最后根据车身设计好整个汽车(Car). 这里就产生了一个"依赖"关系: 汽车依赖车身, 车身依赖底盘, 底盘依赖轮子.

① 传统程序开发

package org.example.iocdemo;public class NewCarExample {public static void main(String[] args) {Car car = new Car();car.run();}
}public class Car {private Framework framework;public Car() {framework = new Framework();System.out.println("Car init...");}public void run() {System.out.println("Car running...");}
}public class Framework {private Bottom bottom;public Framework() {bottom = new Bottom();System.out.println("Framework init...");}
}public class Bottom {private Tire tire;public Bottom() {tire = new Tire();System.out.println("Bottom init...");}
}public class Tire {private int size;public Tire() {size = 17;System.out.println("轮胎尺寸" + size);}
}

上述代码看起来是没有问题的, 但是可维护性非常低. 如果我们后续对轮胎尺寸有修改的需求, 就需要把size设为参数, 那么相关的依赖类也需要跟着改动(加上参数). 修改后的代码如下所示:

package org.example.iocdemo;public class NewCarExample {public static void main(String[] args) {Car car = new Car(13);car.run();}
}public class Car {private Framework framework;public Car(int size) {framework = new Framework(size);System.out.println("Car init...");}public void run() {System.out.println("Car running...");}
}public class Framework {private Bottom bottom;public Framework(int size) {bottom = new Bottom(size);System.out.println("Framework init...");}
}public class Bottom {private Tire tire;public Bottom(int size) {tire = new Tire(size);System.out.println("Bottom init...");}
}public class Tire {private int size;public Tire(int size) {this.size = size;System.out.println("轮胎尺寸" + size);}
}

从上述代码可以看出, 使用传统开发方式的最大问题就是: 当最底层代码改动之后, 整个程序调用链上所有的代码都需要改动. (程序的耦合度非常高 --> 修改一处代码, 其他很多地方都要跟着修改).

解决方案:

在上面的程序中, 我们是根据轮子设计的底盘; 轮子一改, 依赖轮子的底盘就得改; 底盘一改, 依赖底盘的车身就得改; 车身一改, 依赖车身的车就得改. 也就是说, 整个设计全部需要改动 (牵一发而动全身).

那么, 我们可以尝试换一种思路: 

我们先设计出汽车大概的样子, 然后: 根据汽车设计车身, 根据车身设计底盘, 根据底盘设计轮子. 这样一来, 依赖关系就倒置过来了: 轮胎依赖底盘, 底盘依赖车身, 车身依赖汽车.

那如何实现这样的思路呢? 

如果我们还是在当前类中创建自己的下级类对象, 那么当下级类发生改变时, 当前类也要跟着修改. 所以我们不采用这样的方式. 

我们把原来由自己创建的下级类改为传递的方式(也就是"注入"). 这种方式下, 因为我们没有在当前类中创建下级类对象, 所以即使下级类发生变化, 当前类也不需要做任何的修改. 这样一来就完成了程序的解耦合.

② IoC 程序开发

基于上面说的思路, 我们把程序修改一下, 把创建子类的方式改为注入传递的方式. 具体代码实现如下:

package org.example.iocdemo;public class NewCarExample {public static void main(String[] args) {Tire tire = new Tire(22);Bottom bottom = new Bottom(tire);Framework framework = new Framework(bottom);Car car = new Car(framework);car.run();}
}public class Car {private Framework framework;public Car(Framework framework) {this.framework = framework;System.out.println("car init...");}public void run() {System.out.println("Car running");}
}public class Framework {private Bottom bottom;public Framework(Bottom bottom) {this.bottom = bottom;System.out.println("Framework init...");}
}public class Bottom {private Tire tire;public Bottom(Tire tire) {this.tire = tire;System.out.println("Bottom init...");}
}public class Tire {private int size;public Tire(int size) {this.size = size;System.out.println("轮胎尺寸" + size);}
}

经过上述调整, 无论底层类如何变化, 整个调用链的代码都是不用做任何改变的. 这样就完成了代码之间的 "解耦" , 实现了更加灵活, 通用的程序设计方式.

③ IoC 的优势

传统代码中, 对象创建的顺序是: Car --> Framework --> Bottom --> Tire

改进之后的"解耦"代码中, 对象的创建顺序是: Tire --> Bottom --> Framework --> Car

我们发现一个规律: 改进之后的代码, 类的创建顺序是反的. 传统代码是 Car控制并创建了Framework, Framework控制并创建了Bottom, Bottom控制并创建了Tire. 但是改进之后, 控制权发生了反转. 不再是使用方控制并创建依赖对象了, 而是把依赖对象注入当前对象中. 这样的话, 即使依赖类发生任何改变, 当前类都是不受影响的. 

学到这里, 我们大致清楚了什么是控制反转. 那么什么是控制反转容器呢? --> 就是IoC容器.

上图这一部分代码就是IoC容器做的工作.

从上面也可以看出来, IoC容器具备以下优点: 资源不由使用资源的双方管理, 而是由不使用资源的第三方管理.

这样可以带来很多好处

  • 第一: 资源集中管理, 实现资源的可配置和易管理. (IoC容器会帮我们管理一些资源(对象等), 我们需要使用时直接去IoC容器中去取就可以了)
  • 第二: 降低了使用资源双方的依赖程度, 也就是我们说的耦合度. (降低耦合度).

 4. DI

DI, 即 Dependency Injection ("依赖注入"). 容器在运行期间, 动态地为应用程序提供运行时所依赖的资源, 称为"依赖注入".

上述代码中, 就是通过构造函数的方式, 把依赖对象注入到需要使用的对象中的.

IoC 是一种思想或者说是"目标", 而 DI 则是具体的实现. 所以也可以说, DI 是 IoC 的一种实现.

3. IoC & DI 使用

既然 Spring 是一个 IoC 容器. 那么作为容器, 它就有两个最基本的功能: "存" 和 "取".

Spring 容器管理的是对象. 这些对象, 我们称之为"Bean". 我们把这些对象交给Spring管理, 由Spring 来负责对象的创建和销毁. 而我们程序需要做的就是告诉Spring哪些需要存, 以及如何从 Spring 中取出对象.

使用 @Component注解 将类交给Spring管理, 使用 @Autowired注解 实现依赖注入.

我们下面以图书管理系统为例说明:

1. 把Data类交给Spring管理

@Component
public class Data {public List<BookInfo> mockData(){List<BookInfo> list2 = new ArrayList<>();for (int i = 0; i < 5; i++) {BookInfo bookInfo = new BookInfo();bookInfo.setId(i);bookInfo.setBookName("Java编程思想"+i);bookInfo.setCount(1);bookInfo.setPublish("机械工业出版社");bookInfo.setPrice(new Random().nextInt(100));bookInfo.setAuthor("高斯林");bookInfo.setStatus(1);list2.add(bookInfo);}return list2;}
}

2. 把BookService交给Spring管理

@Component
public class BookService {public List<BookInfo> getList(){Data data = new Data();List<BookInfo> list = data.mockData();for (BookInfo bookInfo:list){if (bookInfo.status == 1){bookInfo.setStatusCN("可借阅");}else{bookInfo.setStatusCN("不可借阅");}}return list;}
}

3. 删除创建Data对象的代码, 使用 @Autowired 进行注入.

@Component
public class BookService {@Autowired // 依赖注入(Data对象注入Service)public Data data;public List<BookInfo> getList(){List<BookInfo> list = data.mockData();for (BookInfo bookInfo:list){if (bookInfo.status == 1){bookInfo.setStatusCN("可借阅");}else{bookInfo.setStatusCN("不可借阅");}}return list;}
}

4. 删除创建BookService的代码, 使用 @Autowired 进行注入.

@RequestMapping("/book")
@RestController
public class BookController {@Autowired // 依赖注入 (Service对象注入Controller)public BookService bookService;@RequestMapping("/getList")public List<BookInfo> getList(){List<BookInfo> bookInfos = new ArrayList<>();bookInfos = bookService.getList();return bookInfos;}
}

二. IoC & DI 详解

在前面的图书管理系统案例中, 要把某个类的对象交给IoC容器管理, 就需要在类上添加 @Component 注解.
而 Spring框架 为了更好的服务web应用程序, 还提供了更加丰富的注解.

1. Bean的存储

共有两类注解类型可以实现:
① 类注解: @Controller  @Service  @Repository  @Component  @Configuration
② 方法注解: @Bean

@Controller 用于将接口层代码交给Spring管理.

@Service 用于将逻辑层代码交给Spring管理.

@Repository 用于将持久层代码交给Spring管理.

@Configuration 用于将配置信息代码交给Spring管理.

使用实例: 

@Controller
public class SayHiController {public void sayHi(){System.out.println("hi,Spring");}
}@Service
public class UserService {public void sayHi(){System.out.println("hi,UserService");}
}@Repository
public class UserRepository {public void sayHi(){System.out.println("Hi,UserRepository");}
}

 

这几个注解本质作用都是一样的, 都是将当前类对象交给Spring管理, 只是名字不一样. 这样做是方便程序员一眼看到注解名就能知道当前注解在那一层发挥作用.

@Bean 是方法注解, 作用也是将对象交给Spring管理. 但是方法注解需要搭配类注解来使用, 下面我们来看一个实例:

@Component
public class BeanConfig {@Beanpublic User user(){User user = new User();user.setAge(18);user.setName("zhangsan");return user;}@Beanpublic User user1(){User user1 = new User();user1.setName("lisi");user1.setAge(18);return user1;}
}

2. Bean的重命名 

我们可以通过设置name属性给Bean对象进行重命名:

@Component
public class BeanConfig {@Bean(name = "u")public User user(){User user = new User();user.setAge(18);user.setName("zhangsan");return user;}@Bean(name = "u1")public User user1(){User user1 = new User();user1.setName("lisi");user1.setAge(18);return user1;}
}

一个Bean对象也可以有多个name:

@Component
public class BeanConfig {@Bean(name = {"u","u0"})public User user(){User user = new User();user.setAge(18);user.setName("zhangsan");return user;}
}

3. 扫描路径 

启动类默认的扫描路径是SpringBoot启动类所在包及其子包.

如果程序路径放错, 那么就会发生错误.

三. DI 详解

依赖注入是一个过程, 指的是IoC容器在创建Bean时, 提供运行时所依赖的资源, 而资源指的就是对象. 在前面程序案例中, 我们使用了 @Autowired注解 完成了依赖注入的操作.

一些文章中, 依赖注入也被称为 "对象注入", "属性装配" ...

Spring提供了依赖注入的三种方式:

① 属性注入 (Filed Injection)

② 构造方法注入 (Constructor Injection)

③ Setter注入 (Setter Injection)

1. 属性注入

属性注入是使用 @Autowired注解 实现的, 将 Service类 注入到 Controller类 中.

public class BookController {@Autowired // 依赖注入 (Service对象注入Controller)public BookService bookService;@RequestMapping("/getList")public List<BookInfo> getList(){List<BookInfo> bookInfos = new ArrayList<>();bookInfos = bookService.getList();return bookInfos;}
}

2. 构造方法注入

构造方法注入是在类的构造方法中实现注入.

具体操作就是在类的构造方法的上面加上 @Autowired注解. 如下代码所示:

@Controller
public class UserController2 {public UserService2 userService2;@Autowired //构造方法注入public UserController2(UserService2 userService2) {this.userService2 = userService2;}public void sayHi(){userService2.sayHi();System.out.println("Hi,UserController2");}
}

[注意]: 如果类只有⼀个构造方法, 那么 @Autowired注解 可以省略; 如果类中有多个构造方法, 
那么需要添加上 @Autowired注解 来明确指定到底使用哪个构造方法.

3. Setter注入

Setter注入 和属性的Setter方法实现类似, 只不过在设置 set 方法的时候需要加上 @Autowired注
解. 即:

在一个属性的Setter方法上面加上@Autowired实现注入. 如下代码所示:

@Controller
public class UserController2 {public UserService2 userService2;@Autowired // Setter注入public void setUserService2(UserService2 userService2) {this.userService2 = userService2;}public void sayHi(){userService2.sayHi();System.out.println("Hi,UserController2");}
}

 4. 三种注入方式的优缺点分析

(1) 属性注入

优点: 简洁, 使用方便.

缺点: ① 只能用于IoC容器, 非IoC容器不可使用; ② 不能注入final修饰的属性.

(2) 构造方法注入

优点: ① 可以注入final修饰的属性; ② 注入的对象不会被修改; ③ 依赖对象在使用前一定会被完全初始化 (因为依赖是在类的构造方法中执行的, 而构造方法是在类加载阶段就会执行的方法); ④ 通用性好, 构造方法是JDK支持的, 所以更换任何框架, 他都是适用的.

缺点: 注入多个对象时, 代码会比较繁琐.

(3) Setter注入

优点: 方便类在实例之后, 重新对该对象进行配置或注入.

缺点: ① 不能注入final修饰的属性; ② 注入对象可能会被改变, 因为setter方法可能会被多次调用, 就有被修改的风险. 

相关文章:

Spring IoC DI

目录 一. IoC & DI 入门 1. 重谈Spring 2. 容器 3. IoC ① 传统程序开发 ② IoC 程序开发 ③ IoC 的优势 4. DI 3. IoC & DI 使用 二. IoC & DI 详解 1. Bean的存储 2. Bean的重命名 3. 扫描路径 三. DI 详解 1. 属性注入 2. 构造方法注入 3. Se…...

【Linux】线程、线程控制、地址空间布局

⭐️个人主页&#xff1a;小羊 ⭐️所属专栏&#xff1a;Linux 很荣幸您能阅读我的文章&#xff0c;诚请评论指点&#xff0c;欢迎欢迎 ~ 目录 1、Linux线程1.1 线程的优缺点1.2 线程异常和用途1.3 线程等待1.3 线程终止1.4 线程分离1.5 线程ID和地址空间布局1.6 线程栈 1、…...

【记录】日常|从零散记录到博客之星Top300的成长之路

文章目录 shandianchengzi 2024 年度盘点概述写作风格简介2024年的创作内容总结 shandianchengzi 2024 年度盘点 概述 2024年及2025年至今我创作了786即84篇文章&#xff0c;加上这篇就是85篇。 很荣幸这次居然能够入选博客之星Top300&#xff0c;这个排名在我之前的所有年份…...

网盘资源查找工具---AI功能

01 软件介绍 这是一款融入了ai技术的网盘搜索神器&#xff0c;可以让你更快&#xff0c;更精准的找到自己需要的文件&#xff0c;不管你是找影视&#xff0c;音乐&#xff0c;还是找软件或者学习资料都可以&#xff0c;欢迎前来使用。 02 功能展示 该软件非常简洁&#xff…...

LWJGL轻量级Java游戏库

LWJGL - Lightweight Java Game Library 基本介绍 LWJGL是一个Java库&#xff0c;它支持跨平台访问流行的本地api&#xff0c;这些api在图形&#xff08;OpenGL, Vulkan&#xff09;、音频&#xff08;OpenAL&#xff09;和并行计算&#xff08;OpenCL&#xff09;应用程序的…...

AI智能日志分析系统

文章目录 1.combinations-intelligent-analysis-starter1.目录结构2.pom.xml3.自动配置1.IntelligentAnalysisAutoConfiguration.java2.spring.factories 2.combinations-intelligent-analysis-starter-demo1.目录结构2.pom.xml3.application.yml4.IntelligentAnalysisApplicat…...

详解三种常用标准化:Batch Norm、Layer Norm和RMSNorm

在深度学习中&#xff0c;标准化技术是提升模型训练速度、稳定性和性能的重要手段。本文将详细介绍三种常用的标准化方法&#xff1a;Batch Normalization&#xff08;批量标准化&#xff09;、Layer Normalization&#xff08;层标准化&#xff09;和 RMS Normalization&#…...

数据压缩算法-差分编码(Delta Encoding)

Delta Encoding&#xff08;差分编码&#xff09;是一种数据压缩技术&#xff0c;其核心思想是存储数据之间的差异&#xff08;delta&#xff09;&#xff0c;而不是原始数据本身。这种方法特别适用于数据序列中相邻元素之间变化较小的情况&#xff0c;可以显著减少存储空间或传…...

Nginx中部署多个前端项目

1&#xff0c;准备前端项目 tlias系统的前端资源 外卖项目的前端资源 2&#xff0c;nginx里面的html文件夹中新建&#xff0c;tlias和sky两个文件夹。 切记这是在nginx/html下创建的 mkdir sky mkdir tlias 把tlias和sky的资源都放到对应的文件夹中 3&#xff0c;编辑配置ngi…...

Level DB --- TableBuilder

TableBuilder是Level DB里面重要的类和模块&#xff0c;它描述了数据如何序列化到文件中&#xff0c;以及数据里面的格式逻辑。它里面包含了之前介绍的多个模块和类。 data block、filter block和index block block格式&#xff0c;之前已经介绍过Level DB --- BlockBuilder-…...

JVM堆空间

一、堆空间的核心概述 一个JVM实例只存在一个堆内存&#xff0c;堆也是Java内存管理的核心区域。Java堆区在JVM启动的时候即被创建&#xff0c;其空间大小也就确定了。是JVM管理的最大一块内存空间。 堆内存的大小是可以调节的。堆可以处于物理上不连续的内存空间中&#xff…...

【Numpy核心编程攻略:Python数据处理、分析详解与科学计算】1.13 降维打击:扁平化操作的六种武器

1.13 降维打击&#xff1a;扁平化操作的六种武器 目录 #mermaid-svg-bbLxDryjxBbXe3tu {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-bbLxDryjxBbXe3tu .error-icon{fill:#552222;}#mermaid-svg-bbLxDryjxBbXe3tu…...

Doris Schema Change 常见问题分析

1. 什么是 Schema Change Schema Change 是在数据库中修改表结构的一种操作&#xff0c;例如添加列、删除列、更改列类型等。 ⚠️Schema Change 限制⚠️ 一张表在同一时间只能有一个 Schema Change 作业在运行。分区列和分桶列不能修改。如果聚合表中有 REPLACE 方式聚合的…...

数据结构之堆排序

文章目录 堆排序版本一图文理解 版本二向下调整建堆向上调整建堆 排升/降序升序 堆排序 版本一 基于已有数组建堆取堆顶元素并删除堆顶元素重新建大根堆&#xff0c;完成排序版本。 图文理解 版本二 前提&#xff1a;必须提供有现成的数据结构堆 数组建堆&#xff0c;首尾…...

实现桌面动态壁纸(三)—— 视频播放的策略

关于动态壁纸这边&#xff0c;其实已经不需要再谈什么东西了&#xff0c;现有的各种文章都在介绍相关的技术。可以说现如今要去制作一个桌面动态壁纸应该不是什么难事。我考虑了很久&#xff0c;决定还是开一篇单独谈谈。可能我说的也不全部正确&#xff0c;您有什么建议随时可…...

C语言程序设计十大排序—希尔排序

文章目录 1.概念✅2.希尔排序&#x1f388;3.代码实现✅3.1 直接写✨3.2 函数✨ 4.总结✅ 1.概念✅ 排序是数据处理的基本操作之一&#xff0c;每次算法竞赛都很多题目用到排序。排序算法是计算机科学中基础且常用的算法&#xff0c;排序后的数据更易于处理和查找。在计算机发展…...

2023年版本IDEA复制项目并修改端口号和运行内存

2023年版本IDEA复制项目并修改端口号和运行内存 1 在idea中打开server面板&#xff0c;在server面板中选择需要复制的项目右键&#xff0c;点击弹出来的”复制配置…&#xff08;Edit Configuration…&#xff09;“。如果idea上没有server面板或者有server面板但没有springbo…...

Ubuntu 安装 QGIS LTR 3.34

QGIS官方提供了安装指南&#xff1a;https://qgis.org/resources/installation-guide/#linux。大多数linux发行版将QGIS拆分为几个包&#xff1a;qgis、qgis-python、qgis-grass、qgis-plugin-grass、qgis-server&#xff0c;有的包最初安装时被跳过&#xff0c;可以在需要使用…...

win32汇编环境,对话框程序中使用进度条控件

;运行效果 ;win32汇编环境,对话框程序中使用进度条控件 ;进度条控件主要涉及的是长度单位,每步步长,推进的时间。 ;比如你的长度是1000,步长是100,每秒走1次,则10秒走完全程 ;比如你的长度是1000,步长是10,每秒走1次,则100秒走完全程,但每格格子的长度与上面一样 ;以下…...

从ChatGPT热潮看智算崛起

2025年1月7日&#xff0c;科智咨询发布《2025年IDC产业七大发展趋势》&#xff0c;其中提到“ChatGPT开启生成式AI热潮&#xff0c;智能算力需求暴涨&#xff0c;算力供给结构发生转变”。 【图片来源于网络&#xff0c;侵删】 为何会以ChatGPT发布为节点呢&#xff1f;咱们一起…...

APISIX-API服务网关

一、简介 apisix是一款云原生微服务API网关&#xff0c;可以为API提供终极性能、安全性、开源和可扩展的平台。apisix基于Nginx和etcd实现&#xff0c;与传统API网关相比&#xff0c;apisix具有动态路由和插件热加载&#xff0c;特别适合微服务系统下的API管理。 Apisix 的诞生…...

NR_shell运行流程简析

nr_shell 是一套开源 shell 框架&#xff0c;基于框架可创建终端交互功能。 为了记录终端输入指令&#xff0c;以及进行解析处理&#xff0c;nr_shell 提供了一套 cmd 结构体&#xff0c;具体如下&#xff1a;typedef struct static_cmd_function_struct {char cmd[NR_SHELL_CM…...

leetcode_链表 876.链表的中间节点

876.链表的中间节点 给你单链表的头结点 head &#xff0c;请你找出并返回链表的中间结点。如果有两个中间结点&#xff0c;则返回第二个中间结点。思路&#xff1a;快慢指针&#xff0c;创建两个指针fast和slow&#xff0c;fast指针每次移动两步&#xff0c;slow指针每次移动…...

idea实用设置

一.View 1.配置工具包方便按 二.File->Settings 点开设置然后进行后面的配置 1.这个看个人习惯 2.更新 3.更改菜单字体大小 4.鼠标控制字体大小 5.文件默认字体大小 6. 代码的智能提示功能 7.自动导包 8.编码 9.取消双击shift搜索...

ui-automator定位官网文档下载及使用

一、ui-automator定位官网文档简介及下载 AndroidUiAutomator&#xff1a;移动端特有的定位方式&#xff0c;uiautomator是java实现的&#xff0c;定位类型必须写成java类型 官方地址&#xff1a;https://developer.android.com/training/testing/ui-automator.html#ui-autom…...

Java数据结构方面的面试试题以及答案解析

Java数据结构是在计算机中存储和组织数据的方式&#xff0c;用于高效地处理和管理数据。 以下是一些常见的Java数据结构&#xff1a; 数组&#xff08;Array&#xff09;&#xff1a;一种线性数据结构&#xff0c;允许通过索引快速访问元素。它存储固定大小的相同类型的元素集…...

微信小程序-点餐(美食屋)02开发实践

目录 概要 整体架构流程 &#xff08;一&#xff09;用户注册与登录 &#xff08;二&#xff09;菜品浏览与点餐 &#xff08;三&#xff09;订单管理 &#xff08;四&#xff09;后台管理 部分代码展示 1.index.wxml 2.list.wxml 3.checkout.wxml 4.detail.wxml 小结优点 概要…...

Redis实战(黑马点评)——关于缓存(缓存更新策略、缓存穿透、缓存雪崩、缓存击穿、Redis工具)

redis实现查询缓存的业务逻辑 service层实现 Overridepublic Result queryById(Long id) {String key CACHE_SHOP_KEY id;// 现查询redis内有没有数据String shopJson (String) redisTemplate.opsForValue().get(key);if(StrUtil.isNotBlank(shopJson)){ // 如果redis的数…...

DroneXtract:一款针对无人机的网络安全数字取证工具

关于DroneXtract DroneXtract是一款使用 Golang 开发的适用于DJI无人机的综合数字取证套件&#xff0c;该工具可用于分析无人机传感器值和遥测数据、可视化无人机飞行地图、审计威胁活动以及提取多种文件格式中的相关数据。 功能介绍 DroneXtract 具有四个用于无人机取证和审…...

uniapp使用uni.navigateBack返回页面时携带参数到上个页面

我们平时开发中也经常遇到这种场景&#xff0c;跳转一个页面会进行一些操作&#xff0c;操作完成后再返回上个页面同时要携带着一些参数 其实也很简单&#xff0c;也来记录一下吧 假设从A页面 跳转到 B页面 A页面 直接上完整代码了哈&#xff0c;很简单&#xff1a; <t…...

2025美赛MCM数学建模A题:《石头台阶的“记忆”:如何用数学揭开历史的足迹》(全网最全思路+模型)

✨个人主页欢迎您的访问 ✨期待您的三连 ✨ 《石头台阶的“记忆”&#xff1a;如何用数学揭开历史的足迹》 目录 《石头台阶的“记忆”&#xff1a;如何用数学揭开历史的足迹》 ✨摘要✨ ✨引言✨ 1. 引言的结构 2. 撰写步骤 &#xff08;1&#xff09;研究背景 &#…...

python远程获取数据库中的相关数据并存储至json文件

1. conn中的5个变量的含义&#xff1a; ① Driver&#xff1a;数据库驱动程序&#xff0c;我使用的是SQL Server数据库。 ② Server&#xff1a;数据库所在的服务器地址。 ③ Database&#xff1a;要连接的数据库的名称。 ④ UID&#xff1a;登录 SQL Server 数据库的用户名…...

DeepSeek-R1解读:纯强化学习,模型推理能力提升的新范式?

DeepSeek-R1解读&#xff1a;纯强化学习&#xff0c;模型推理能力提升的新范式&#xff1f; 1. Impressive Points2. 纯强化学习&#xff0c;LLM推理能力提升新范式&#xff1f;2.1 DeepSeek-R1-Zero2.2 DeepSeek-R1 3. 端侧模型能力提升&#xff1a;蒸馏>强化学习 1. Impre…...

系统安全及应用

一&#xff1a;账号安全控制 1.1 系统账号清理 1.1.1 将非登陆用户的Shell 设置为 /sbin/nologin (设置为这个解释器&#xff0c;禁止用户登陆&#xff09; [rootlocalhost ~]# usermod -s /sbin/nologin zhangsan #将用户zhangsan 的登录解释器 设置为 /sbin/n…...

ubuntu解决普通用户无法进入root

项目场景&#xff1a; 在RK3566上移植Ubuntu20.04之后普通用户无法进入管理员模式 问题描述 在普通用户使用sudo su试图进入管理员模式的时候报错 解决方案&#xff1a; 1.使用 cat /etc/passwd 查看所有用户.最后一行是 若无用户&#xff0c;则使用 sudo useradd -r -m -s /…...

Mac m1,m2,m3芯片使用nvm安装node14报错

使用nvm安装了node 12/16/18都没有问题&#xff0c;到14就报错了。第一次看到这个报错有点懵&#xff0c;查询资料发现是Mac芯片的问题。 Issue上提供了两个方案&#xff1a; 1、为了在arm64的Mac上安装node 14&#xff0c;需要使用Rosseta&#xff0c;可以通过以下命令安装 …...

IDEA工具下载、配置和Tomcat配置

1. IDEA工具下载、配置 1.1. IDEA工具下载 1.1.1. 下载方式一 官方地址下载 1.1.2. 下载方式二 官方地址下载&#xff1a;https://www.jetbrains.com/idea/ 1.1.3. 注册账户 官网地址&#xff1a;https://account.jetbrains.com/login 1.1.4. JetBrains官方账号注册…...

实战网络安全:渗透测试与防御指南

&#x1f4dd;个人主页&#x1f339;&#xff1a;一ge科研小菜鸡-CSDN博客 &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; 引言 在数字化时代&#xff0c;网络安全已成为企业和个人不可忽视的重要课题。网络攻击的复杂性与日俱增&#xff0c;从数据泄露…...

Vue 3 中的 toRef 与 toRefs:使用与案例解析

在 Vue 3 的响应式系统中&#xff0c;toRef 和 toRefs 是两个非常实用的工具函数。它们主要用于将响应式对象的属性转换为单独的 ref&#xff0c;以便在模板或逻辑中更方便地使用。本文将详细介绍 toRef 和 toRefs 的用法&#xff0c;并通过一个老师信息的案例来演示它们的实际…...

如何让Dev-C++支持C++11及以上标准

目录 问题描述解决方案步骤1&#xff1a;打开编译选项 问题描述 在Dev-C中使用C11/17/20新特性&#xff08;如pop_back()等&#xff09;时&#xff0c;可能出现编译错误&#xff1a; #include <iostream> #include<string> using namespace std; int main() {str…...

java8-日期时间Api

目录 LocalDate更新时间LocalTimeLocalDateTimeInstantPeriod Duration格式化、解析日期-时间对象时区 java.util.Date java.util.Calendar 不支持时区 线程不安全 月份从0起线程不安全&#xff0c;只有包裹在ThreadLocal中才安全 java.text.DateFormat java.text.SimpleDateFo…...

电脑无法开机,重装系统后没有驱动且驱动安装失败

电脑无法开机&#xff0c;重装系统后没有驱动且驱动安装失败 前几天电脑突然坏了&#xff0c;电脑卡住后&#xff0c;强制关机&#xff0c;再开机后开机马上就关机。尝试无数次开机后失败&#xff0c;进入BIOS界面&#xff0c;发现已经没有Windows系统了。重新安装系统后&…...

Vue.js 传递路由参数和查询参数

Vue.js 传递路由参数和查询参数 在 Vue.js 开发中&#xff0c;Vue Router 提供了灵活的方式来处理路由参数和查询参数&#xff0c;使得组件能够根据不同的路径或查询条件渲染相应的内容。 路由参数 路由参数&#xff08;也称为路径参数&#xff09;是 URL 路径的一部分&…...

Java 反射机制介绍

Java学习资料 Java学习资料 Java学习资料 一、引言 在 Java 编程里&#xff0c;反射机制是一项强大且独特的特性。它赋予程序在运行时动态地获取类的信息&#xff0c;并且可以操作类或对象的属性、方法和构造函数等。借助反射机制&#xff0c;程序的灵活性和可扩展性得到显著…...

Final2x--开源AI图片放大工具

Final2x--开源AI图片放大工具 链接&#xff1a;https://pan.xunlei.com/s/VOHSklukQAquUn3GE7eHJXfOA1?pwdr3r3#...

TCP全连接队列

1. 理解 int listen(int sockfd, int backlog) 第二个参数的作用 backlog&#xff1a;表示tcp全连接队列的连接个数1。 如果连接个数等于backlog1&#xff0c;后续连接就会失败&#xff0c;假设tcp连接个数为0&#xff0c;最大连接个数就为1&#xff0c;并且不accept获取连接…...

前端力扣刷题 | 4:hot100之 子串

560. 和为K的子数组 给你一个整数数组 nums 和一个整数 k &#xff0c;请你统计并返回 该数组中和为 k 的子数组的个数 。 子数组是数组中元素的连续非空序列。 示例&#xff1a; 输入&#xff1a;nums [1,1,1], k 2 输出&#xff1a;2 法一&#xff1a;暴力法 var subar…...

【精选】基于数据挖掘的招聘信息分析与市场需求预测系统 职位分析、求职者趋势分析 职位匹配、人才趋势、市场需求分析数据挖掘技术 职位需求分析、人才市场趋势预测

博主介绍&#xff1a; ✌我是阿龙&#xff0c;一名专注于Java技术领域的程序员&#xff0c;全网拥有10W粉丝。作为CSDN特邀作者、博客专家、新星计划导师&#xff0c;我在计算机毕业设计开发方面积累了丰富的经验。同时&#xff0c;我也是掘金、华为云、阿里云、InfoQ等平台…...

字节跳动发布UI-TARS,超越GPT-4o和Claude,能接管电脑完成复杂任务

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…...

2025课题推荐——USBL和DVL的误差建模与补偿

在海洋探测与研究中&#xff0c;定位技术的准确性至关重要。超短基线&#xff08;USBL&#xff09;和多普勒速度计&#xff08;DVL&#xff09;是两种广泛应用于水下定位和导航的技术&#xff0c;它们在深海探测、海洋工程和水下机器人等领域发挥着重要作用。然而&#xff0c;这…...