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

浅谈Spring

Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器(框架)。

一、什么是IOC?

IoC = Inversion of Control 翻译成中⽂是“控制反转”的意思,也就是说 Spring 是⼀个“控制反转”的容器。

1.1控制反转推导

这个控制反转怎么理解呢?我们来推导一下这个过程:

我们现在构建⼀辆“⻋”的程序,我们的实现思路和代码实现是这样的:

轮胎的尺⼨的固定的,然⽽随着对的⻋的需求量越来越⼤,个性化需求也会越来越多,这时候我们就需要加⼯多种尺⼨的轮胎,那这个时候就要对上面的程序进⾏修改了,修改后的代码如下所示:

从上面的代码中可以看出传统写法的缺陷:代码耦合性太高

那上述问题我们可以怎么解决呢?

这就好⽐我们打造⼀辆完整的汽车,传统的方式是所有的配件都是⾃⼰造,那么当客户需求发⽣改变的时候,⽐如轮胎的尺⼨不再是原来的尺⼨了,那我们要⾃⼰动⼿来改了,但如果我们是把轮胎外包出去,那么即使是轮胎的尺⼨发⽣变变了,我们只需要向代理⼯⼚下订单就⾏了,我们⾃身是不需要出⼒的。

所以:我们可以尝试不在每个类中自己创建下级类,如果⾃⼰创建下级类就会出现当下级类发⽣改变操作,⾃⼰也要跟着修改。
此时,我们只需要将原来由自己创建的下级类,改为传递的方式(也就是注入的方式),因为我们不需要在当前类中创建下级类了,所以下级类即使发生变化(创建或减少参数),当前类本身也⽆需修改任何代码,这样就完成了程序的解耦。

代码实现思路如下:

总结对比一下:

执行顺序:

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

通⽤程序的实现代码,类的创建顺序是反的,传统代码是 Car 控制并创建了Framework,Framework 创建并创建了 Bottom,依次往下,⽽改进之后的控制权发⽣的反转,不再是上级对象创建并控制下级对象了,⽽是下级对象把注⼊将当前对象中,下级的控制权不再由上级类控制了,这样即使下级类发⽣任何改变,当前类都是不受影响的,这就是典型的控制反转,也就是 IoC 的实
现思想。

上述过程不知道各位小伙伴能不能理解,但总结来说就是传统的写法所有的东西都是由程序去控制创建的,改进后的写法是由调用者自行控制创建对象 , 把主动权交给了调用者 . 程序不用去管怎么创建,怎么实现了 . 它只负责提供一个接口 .。

这种思想 , 从本质上解决了问题 , 我们程序员不再去管理对象的创建了 , 更多的去关注业务的实现 . 耦合性大大降低 . 这也就是IOC的原型 。

1.2、IOC的本质:

控制反转IoC(Inversion of Control),是一种设计思想,DI(依赖注入)是实现IoC的一种方法,也有人认为DI只是IoC的另一种说法。没有IoC的程序中 , 我们使用面向对象编程 , 对象的创建与对象间的依赖关系完全硬编码在程序中,对象的创建由程序自己控制,控制反转后将对象的创建转移给第三方,个人认为所谓控制反转就是:获得依赖对象的方式反转了。

1.2.1、DI依赖注入

说到 IoC 不得不提的⼀个词就是“DI”,DI 是 Dependency Injection 的缩写,翻译成中⽂是“依赖注
⼊”的意思。
所谓依赖注⼊,就是由 IoC 容器在运⾏期间,动态地将某种依赖关系注⼊到对象之中。所以,依
赖注⼊(DI)和控制反转(IoC)是从不同的⻆度的描述的同⼀件事情,就是指通过引⼊ IoC 容
器,利⽤依赖关系注⼊的⽅式,实现对象之间的解耦。
IoC 是“⽬标”也是⼀种思想,⽽⽬标和思想只是⼀种指导原则,最终还是要有可⾏的落地⽅案,⽽ DI就属于具体的实现。

DI 概念说明:

将对象存放到容器中的好处:将对象存储在 IoC 容器相当于将以后可能⽤的所有⼯具制作好都放到仓库中,需要的时候直接取就⾏了,⽤完再把它放回到仓库。⽽ new 对象的⽅式相当于,每次需要⼯具了,才现做,⽤完就扔掉了也不会保存,下次再⽤的时候还得重新做,这就是 IoC 容器和普通程序开发的区别

二、创建有一个Spring项目

1、配置maven国内源

2、创建spring项目

<dependencies>
        <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-context</artifactId>
                <version>5.2.3.RELEASE</version>
</dependency>
<dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-beans</artifactId>
                <version>5.2.3.RELEASE</version>
</dependency>
</dependencies>

按照上述步骤配置完成,启动成功不报错,那么一个spring项目就创建好了,接下来我们体验一下Spring是如何获取和使用Bean的。

3、获取和使用Spring对象

3.1、添加 Spring 配置⽂件 spring-config.xml

在创建好的项⽬中添加 Spring 配置⽂件 spring-config.xml,将此⽂件放到 resources 的根⽬录下

Spring 配置⽂件的固定格式为以下内容(以下内容⽆需记忆,只需要保存到⾃⼰可以找到的地

就可以了,因为它是固定不变的)

<?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 htt
p://www.springframework.org/schema/beans/spring-beans.xsd">
</beans>

3.2、将Bean对象存储到Spring(IOC容器)

【解释一下:这里的我们正常创建一个类是这么写的:类型   变量名 = new 类型();bean中的 id 相当于变量名,class 相当于 new的对象】

3.2、从容器中获取Bean对象

获取并使⽤ Bean 对象,分为以下 3 步:

  1. 得到 Spring 上下文对象,因为对象都交给 Spring 管理了,所以获取对象要从 Spring 中获取,那么就得先得到 Spring 的上下文。
  2. 通过 Spring 上下文,获取某⼀个指定的 Bean 对象。
  3. 使⽤ Bean 对象。

如果取多个 Bean 的话重复以上第 2、3 步骤。

除了 ApplicationContext 之外,我们还可以使⽤ BeanFactory 来作为 Spring 的上下⽂,如下代码所示:

BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("springconfig.xml"));

ApplicationContext 和BeanFactory 的区别

3.3、getBean ⽅法的更多⽤法

getBean() ⽅法有很多种重载⽅法,我们也可以使⽤其他⽅式来获取 Bean 对象

三、Spring 更简单的读取和存储对象——注解

3.1、配置扫描路径

前置工作,在之前的spring-config.xml文件中配置bean的扫描路径,如果不配置,后面所有的操作都不会生效。

3.2、注解

想要将对象存储在 Spring 中,有两种注解类型可以实现:

  • 类注解:@Controller、@Service、@Repository、@Component、@Configuration。
  • 方法注解:@Bean。

3.2.1、五类注解

@Controller // 将对象存储到 Spring 中
public class UserController {
public void sayHi(String name) {
System.out.println("Hi," + name);
}
}public class Application {
public static void main(String[] args) {
// 1.得到 spring 上下⽂
ApplicationContext context =
new ClassPathXmlApplicationContext("spring-config.xml");
// 2.得到 bean
UserController userController = (UserController) context.getBean(
"userController");
// 3.调⽤ bean ⽅法
userController.sayHi("Bit");
}
}========================
@Service
public class UserService {
public void sayHi(String name) {
System.out.println("Hi," + name);
}
}class App {
public static void main(String[] args) {
// 1.得到 spring 上下⽂
ApplicationContext context =
new ClassPathXmlApplicationContext("spring-config.xml");
// 2.得到 bean
UserService userService = (UserService) context.getBean("userServi
ce");
// 3.调⽤ bean ⽅法
userService.sayHi("Bit");
}
}
=======================================
@Repository
public class UserRepository {
public void sayHi(String name) {
System.out.println("Hi," + name);
}
}class App {
public static void main(String[] args) {
// 1.得到 spring 上下⽂
ApplicationContext context =
new ClassPathXmlApplicationContext("spring-config.xml");
// 2.得到某个 bean
UserRepository userRepository = (UserRepository) context.getBean(
"userRepository");
// 3.调⽤ bean ⽅法
userRepository.sayHi("Bit");
}
}
=================================================
@Component
public class UserComponent {
public void sayHi(String name) {
System.out.println("Hi," + name);
}
}class App {
public static void main(String[] args) {
// 1.得到 spring 上下⽂
ApplicationContext context =
new ClassPathXmlApplicationContext("spring-config.xml");
// 2.得到某个 bean
UserComponent userComponent = (UserComponent) context.getBean("use
rComponent");
// 3.调⽤ bean ⽅法
userComponent.sayHi("Bit");
}
}
=======================
@Configuration
public class UserConfiguration {
public void sayHi(String name) {
System.out.println("Hi," + name);
}
}
class App {
public static void main(String[] args) {
// 1.得到 spring 上下⽂
ApplicationContext context =
new ClassPathXmlApplicationContext("spring-config.xml");
// 2.得到某个 bean
UserConfiguration userConfiguration = (UserConfiguration) context.
getBean("userConfiguration");
// 3.调⽤ bean ⽅法
userConfiguration.sayHi("Bit");
}
}

观察上述代码,可以发现,这五个注解的功能是一样的,那么我们为什么要用那么多个注解呢?用一个不就行了?

这和为什么每个省/市都有⾃⼰的⻋牌号是⼀样的?⽐如陕⻄的⻋牌号就是:陕X:XXXXXX,北京的⻋牌号:京X:XXXXXX,⼀样。甚⾄⼀个省不同的县区也是不同的,⽐如⻄安就是,陕A:XXXXX,咸阳:陕B:XXXXXX,宝鸡,陕C:XXXXXX,⼀样。这样做的好处除了可以节约号码之外,更重要的作⽤是可以直观的标识⼀辆⻋的归属地
同理,我们使用那么多的类注解也是相同的原因,就是让程序员看到类注解之后,就能直接了解当前类的⽤途:

这五类注解的用途如下:

@Controller   【控制器】 校验参数的合法性(相当于安检系统)

@Service       【服务】业务组装(客服中心)

@Repository 【数据持久层】实际业务处理中心(实际办理业务的)

@Component【组件】工具类层(基础的工具)

@Configuration【配置层】配置

程序的工程分层,调⽤流程如下:

这五个注解之间的关系:

我们查看源码后发现,其实这些注解⾥⾯都有⼀个注解 @Component,说明它们本身就是属于 @Component 的“子类”

方法注解@Bean

类注解是添加到某个类上的,而方法注解是放到某个⽅法上的,如以下代码的实现:


3.3、Bean命名规则

3.3.1、@Bean的重命名:

3.4、获取 Bean 对象(对象装配)

获取 bean 对象也叫做对象装配,是把对象取出来放到某个类中,有时候也叫对象注⼊
对象装配(对象注⼊)的实现⽅法以下 3 种:

  1. 属性注⼊
  2.  构造⽅法注⼊
  3. Setter 注⼊

3.4.1、 属性注⼊

属性注⼊是使用 @Autowired 实现的,将 Service 类注⼊到 Controller 类中。
Service 类的实现代码如下:

@Service
public class UserService {public User getUser(Integer id) {
// 伪代码,不连接数据库
User user = new User();
user.setId(id);
user.setName("Java-" + id);
return user;
}
}

Controller 类的实现代码如下:

@Controller
public class UserController {
// 注⼊⽅法1:属性注⼊
@Autowired
private UserService userService;   //属性注入的核心代码public User getUser(Integer id) {
return userService.getUser(id);
}
}

获取 Controller 中的 getUser ⽅法:

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
public class UserControllerTest {
public static void main(String[] args) {
ApplicationContext context =
new ClassPathXmlApplicationContext("spring-config.xml");
UserController userController = context.getBean(UserController.cla
ss);
System.out.println(userController.getUser(1).toString());
}
}

最终结果如下:

3.4.1.1、注意:  同类型的Bean存储到容器多个,获取时会报错

@Component
public class Users {
@Bean
public User user1() {
User user = new User();
user.setId(1);
user.setName("Java");
return user;
}
@Bean
public User user2() {
User user = new User();
user.setId(2);
user.setName("MySQL");
return user;
}

在另⼀个类中获取 User 对象,代码和运行结果如下:

解决方案:

1. 使⽤ @Resource(name="")
2. 使⽤ @Qualifier("")

3.4.1.2、属性注入的优缺点:

3.4.2、Setter 注入

Setter 注入和属性的 Setter ⽅法实现类似,只不过在设置 set ⽅法的时候需要加上 @Autowired 注解(不能省),Controller 类的实现代码如下:

@Controller
public class UserController3 {
// 注⼊⽅法3:Setter注⼊
private UserService userService;
@Autowired
public void setUserService(UserService userService) {
this.userService = userService;
}
public User getUser(Integer id) {
return userService.getUser(id);
}
}

3.4.1.1、Setter注入优缺点:

3.4.3、构造方法注入

构造⽅法注⼊是在类的构造⽅法中实现注⼊,Controller 类的实现代码如下:

@Controller
public class UserController2 {
// 注⼊⽅法2:构造⽅法注⼊
private UserService userService;
@Autowired
public UserController2(UserService userService) {
this.userService = userService;
}
public User getUser(Integer id) {
return userService.getUser(id);
}
}

注意:如果只有⼀个构造⽅法,那么 @Autowired 注解可以省略,如下图所示:

3.4.3.1、构造方法注入优缺点:

Spring为什么使用三级缓存解决循环依赖?_哔哩哔哩_bilibili

3.2.4、三种注入优缺点分析

  • 属性注⼊的优点是简洁,使用方便;缺点是只能⽤于 IoC 容器,如果是⾮ IoC 容器不可⽤,并且只有在使⽤的时候才会出现 NPE(空指针异常)。
  • 构造⽅法注⼊是 Spring 推荐的注入方式,它的缺点是如果有多个注⼊会显得⽐较臃肿,但出现这种情况你应该考虑⼀下当前类是否符合程序的单⼀职责的设计模式了,它的优点是通⽤性,在使⽤之前⼀定能把保证注⼊的类不为空。
  • Setter ⽅式是 Spring 前期版本推荐的注⼊⽅式,但通⽤性不如构造⽅法,所有 Spring 现版本已经推荐使⽤构造⽅法注⼊的⽅式来进⾏类注入了。

 @Resource:另⼀种注⼊关键字
在进⾏类注⼊时,除了可以使⽤ @Autowired 关键字之外,我们还可以使⽤ @Resource 进⾏注⼊:

@Controller
public class UserController {
// 注⼊
@Resource
private UserService userService;
public User getUser(Integer id) {
return userService.getUser(id);
}
}

@Autowired 和 @Resource 的区别

四、Bean 作⽤域和⽣命周期

4.1、作用域

限定程序中变量的可⽤范围叫做作⽤域,或者说在源代码中定义变量的某个区域就叫做作⽤域。
⽽ Bean 的作⽤域是指 Bean 在 Spring 整个框架中的某种⾏为模式,
⽐如 singleton 单例作⽤域,就表示 Bean 在整个 Spring 中只有⼀份,它是全局共享的,那么当其他⼈修改了这个值之后,那么另⼀个⼈读取到的就是被修改的值
Spring 容器在初始化⼀个 Bean 的实例时,同时会指定该实例的作⽤域。

Spring有 6 种作⽤域,最后四种是基于 Spring MVC ⽣效的:
1. singleton:单例作⽤域(单例模式,默认的作用域)
2. prototype:原型作⽤域(原型模式,多例作⽤域)
3. request:请求作⽤域,只适用于SpringMVC项目(Spring Web)
4. session:回话作⽤域,一个Http会话共享一个Bean。只适用于SpringMVC项目(Spring Web)
5. application:应用作用域(全局作用域)表示的是一个Context容器共享一个作用域。只适用于SpringMVC项目(Spring Web)
6. websocket:HTTP WebSocket 作⽤域,只适用于websocket作用域。

单例作用域(singleton) VS 全局作用域(application)

singleton 是 Spring Core 的作⽤域;application 是 Spring Web 中的作用域;
singleton 作⽤于 IoC 的容器,而 application 作⽤于 Servlet 容器。

4.2、设置作⽤域

使⽤ @Scope 标签就可以⽤来声明 Bean 的作⽤域,⽐如设置 Bean 的作⽤域,如下代码所示:

@Component
public class Users {
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
@Bean(name = "u1")
public User user1() {
User user = new User();
user.setId(1);
user.setName("Java"); 
return user;
}
}

@Scope 标签既可以修饰方法也可以修饰类,@Scope 有两种设置⽅式:

  1. 直接设置值:@Scope("prototype")
  2. 使⽤枚举设置:@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)

4.3、Spring 执⾏流程

启动 Spring 容器 -> 实例化 Bean(分配内存空间,从⽆到有) -> Bean 注册到 Spring 中(存操作) -> 将 Bean 装配到需要的类中(取操作)。
4.4、Bean 生命周期
所谓的⽣命周期指的是⼀个对象从诞⽣到销毁的整个生命过程,我们把这个过程就叫做⼀个对象的生命周期。
Bean 的⽣命周期分为以下 5 ⼤部分:
1.实例化 Bean(为 Bean 分配内存空间)
2.设置属性(Bean 注⼊和装配)
3.Bean 初始化

实现了各种 Aware 通知的⽅法,如 BeanNameAware、BeanFactoryAware、
ApplicationContextAware 的接⼝⽅法;
执⾏ BeanPostProcessor 初始化前置⽅法;
执⾏ @PostConstruct 初始化⽅法,依赖注⼊操作之后被执⾏;
执⾏⾃⼰指定的 init-method ⽅法(如果有指定的话);
执⾏ BeanPostProcessor 初始化后置⽅法。


4.使⽤ Bean
5.销毁 Bean

4.4、实例化和初始化的区别


实例化和属性设置是 Java 级别的系统“事件”,其操作过程不可人工干预和修改;⽽初始化是给开发者提供的,可以在实例化之后,类加载完成之前进行自定义“事件”处理


以上就是本文分享的主要内容,对你有帮助的话,可以点个赞哦~~

相关文章:

浅谈Spring

Spring是一个轻量级的控制反转(IoC)和面向切面(AOP)的容器&#xff08;框架&#xff09;。 一、什么是IOC&#xff1f; IoC Inversion of Control 翻译成中⽂是“控制反转”的意思&#xff0c;也就是说 Spring 是⼀个“控制反转”的容器。 1.1控制反转推导 这个控制反转怎…...

Java 复习笔记 - 面向对象进阶篇

文章目录 一&#xff0c;Static&#xff08;一&#xff09;Static的概述&#xff08;二&#xff09;静态变量&#xff08;三&#xff09;静态方法&#xff08;四&#xff09;工具类&#xff08;五&#xff09;static的注意事项 二&#xff0c;继承&#xff08;一&#xff09;继…...

微信小程序中识别html标签的方法

rich-text组件 在微信小程序中有一个组件rich-text可以识别文本节点或是元素节点 具体入下: //需要识别的数据放在data中,然后放在nodes属性中即可 <rich-text nodes"{{data}}"></rich-text>详情可以参考官方文档:https://developers.weixin.qq.com/mi…...

02_常见网络层协议的头结构

1.ARP报文的报文结构 ARP首部的5个字段的含义&#xff1a; 硬件类型&#xff1a;值为1表示以太网MAC地址。 协议类型&#xff1a;表示要映射的协议地址类型&#xff0c;0x0800 表示映射为IP地址。 硬件地址长度&#xff1a;在以太网ARP的请求和应答中都是6&#xff0c;表示M…...

ChatGLM学习

GLM paper&#xff1a;https://arxiv.org/pdf/2103.10360.pdfchatglm 130B&#xff1a;https://arxiv.org/pdf/2210.02414.pdf 前置知识补充 双流自注意力 Two-stream self-attention mechanism&#xff08;双流自注意机制&#xff09;是一种用于自然语言处理任务的注意力机制…...

Flink之Watermark

1.乱序问题 流处理从事件产生&#xff0c;到流经source&#xff0c;再到operator&#xff0c;中间是有一个过程和时间的&#xff0c;虽然大部分情况下&#xff0c;流到operator的数据都是按照事件产生的时间顺序来的&#xff0c;但是也不排除由于网络、分布式等原因&#xff0…...

二轮平衡小车3:PID速度环

使用芯片&#xff1a;STM32 F103 C8T6 今日继续我的二路平衡小车开发之路&#xff0c;今日编写的是二轮平衡小车的PID速度环&#xff0c;我准备了纸飞机串口助手软件来辅助测试调节PID。 本文主要贴代码&#xff0c;之前的文章都有原理&#xff0c;代码中相应初始化驱动部分也…...

C语言之练习题

欢迎来到我的世界 希望这篇文章对你有所帮助&#xff0c;有不足的地方还请指正&#xff0c;大家一起学习交流 ! 目录 前言编程题第一题&#xff1a;珠玑妙算第二题&#xff1a;寻找奇数第三题&#xff1a;寻找峰值第四题&#xff1a;数对 总结 前言 这是暑假题目的收尾文章&am…...

没钱,没人,没经验?传统制造型企业如何用无代码实现转型

2023年&#xff0c;国家市场监督管理总局发布了三项重要标准&#xff0c;包括《工业互联网平台选型要求》、《工业互联网平台微服务参考框架》和《工业互联网平台开放应用编程接口功能要求》。这些标准的发布对于完善工业互联网平台标准体系&#xff0c;提升多样化工业互联网平…...

CentOS ARM 部署 kubernetes v1.24.6

1.背景 之前安装的kubernetes版本为v1.19.0 树莓派使用(CentOS7.9 armv71 Kubernetes1.19.0), 由于版本过低&#xff0c;一些HPA相关的功能支持不是特别好&#xff0c;因此需要将版本升级&#xff0c;本次会将版本升级为v1.24.6. 2. 如何upgrade 2.1. 优雅升级 kubeadm自带…...

LeetCode 725. Split Linked List in Parts【链表】中等

本文属于「征服LeetCode」系列文章之一&#xff0c;这一系列正式开始于2021/08/12。由于LeetCode上部分题目有锁&#xff0c;本系列将至少持续到刷完所有无锁题之日为止&#xff1b;由于LeetCode还在不断地创建新题&#xff0c;本系列的终止日期可能是永远。在这一系列刷题文章…...

云计算中的负载均衡技术,确保资源的平衡分配

文章目录 1. 硬件负载均衡器2. 软件负载均衡器3. DNS负载均衡4. 内容分发网络&#xff08;CDN&#xff09; &#x1f388;个人主页&#xff1a;程序员 小侯 &#x1f390;CSDN新晋作者 &#x1f389;欢迎 &#x1f44d;点赞✍评论⭐收藏 ✨收录专栏&#xff1a;云计算 ✨文章内…...

探索 SOCKS5 代理在跨境电商中的网络安全应用

随着全球化的发展&#xff0c;跨境电商成为了商业界的一颗新星&#xff0c;为企业提供了无限的发展机遇。然而&#xff0c;随之而来的是网络安全的挑战&#xff0c;特别是在处理国际网络流量时。在这篇文章中&#xff0c;我们将探讨如何利用 SOCKS5 代理和代理 IP 技术来加强跨…...

全网独家:编译CentOS6.10系统的openssl-1.1.1多版本并存的rpm安装包

CentOS6.10系统原生的openssl版本太老&#xff0c;1.0.1e&#xff0c;不能满足一些新版本应用软件的要求&#xff0c;但是它又被wget、mysql-libs、python-2.6.6、yum等一众系统包所依赖&#xff0c;不能再做升级。故需考虑在不影响系统原生openssl的情况下&#xff0c;安装较新…...

【go】异步任务解决方案Asynq实战

文章目录 一.Asynq介绍二.所需工具三.代码示例四.Reference 一.Asynq介绍 Asynq 是一个 Go 库&#xff0c;一个高效的分布式任务队列。 Asynq 工作原理&#xff1a; 客户端&#xff08;生产者&#xff09;将任务放入队列服务器&#xff08;消费者&#xff09;从队列中拉出任…...

掌握 Android 自动化测试框架 UiAutomator UiAutomator2

掌握 Android 自动化测试框架 UiAutomator & UiAutomator2 一、UiAutomator 简介二、UiAutomator2 的诞生三、UiAutomator2 的应用实践总结你是否曾经在进行 Android 应用开发时,对于如何进行全面、有效的自动化测试感到困惑?你是否想要更高效地进行 UI 测试,而不是一遍…...

c#抽象类(abstract)

概述&#xff1a; C#中的抽象类是一种特殊类型的类&#xff0c;它不能被实例化&#xff0c;只能被继承。抽象类用于提供一个共享的基类&#xff0c;其中定义了一些方法和属性的签名&#xff0c;但没有具体的实现。这些方法和属性可以在派生类中进行实现。 使用抽象类的主要目…...

语义分割实践思考记录(个人备忘录)

一、任务管理器、NVDIA的GPU利用率显示[1][2] 若需要在任务管理器中查看基于Pytorch框架的GPU利用率&#xff0c;那么&#xff0c;我们需要将监控面板监测内容调整为cuda。图一&#xff08;左&#xff09;即为英伟达命令行工具面板。 图一 英伟达GPU使用率监控 二、基于混淆矩阵…...

Zebec Protocol 成非洲利比亚展会合作伙伴,并将向第三世界国家布局

在 9 月 6 日&#xff0c;The Digital Asset Summit ’23&#xff08;利比亚大会&#xff09;在尼日利亚首度阿布贾的 NAF 会议中心举办&#xff0c;该会议对 Web3 领域在非洲地区的发展进行了探索&#xff0c;旨在推动非洲地区区块链产业的进一步发展&#xff0c;据悉该会议室…...

随机流-RandomAccessFile

RandomAccessFile RandomAccessFile 基本操作案例 RandomAccessFile 基本操作 案例 import java.io.*;public class TestMain09 {public static void main(String[] args) throws Exception {insert("D:\\home\\product\\aa.txt",2,"ni");}public static…...

单例和静态类

C#中的单例&#xff08;Singleton&#xff09;和静态类&#xff08;Static Class&#xff09;是两种不同的设计模式&#xff0c;它们各自有不同的用途和特点。 单例模式是一种设计模式&#xff0c;它确保一个类只有一个实例&#xff0c;并提供全局访问点。通常&#xff0c;单例…...

PMP-项目风险管理的重要性

一、什么是项目风险管理 项目风险管理旨在识别和管理未被其他项目管理过程所管理的风险。如果不妥善管理&#xff0c;这些风险有可能导致项目偏离计划&#xff0c;无法达成既定的项目目标。因此&#xff0c;项目风险管理的有效性直接关乎项目成功与否。 每个项目都在两个层面…...

学习的心得

文章目录 第一节课心得**学会了敲写数学公式** 第一节课心得 老师讲得非常好&#xff0c;我们下载了xmind&#xff0c;如何制作思维导图 学会了敲写数学公式 ∫ 10 20 ( x 2 − 3 x 2 ) d x \displaystyle\int_{10}^{20}(x^2-3x2)dx ∫1020​(x2−3x2)dx...

Python网络爬虫中这七个li标签下面的属性值,不是固定的,怎样才能拿到他们的值呢?...

点击上方“Python爬虫与数据挖掘”&#xff0c;进行关注 回复“书籍”即可获赠Python从入门到进阶共10本电子书 今 日 鸡 汤 愚以为宫中之事&#xff0c;事无大小&#xff0c;悉以咨之&#xff0c;然后施行&#xff0c;必能裨补阙漏&#xff0c;有所广益。 大家好&#xff0c;我…...

白鲸开源 DataOps 平台加速数据分析和大模型构建

作者 | 李晨 编辑 | Debra Chen 数据准备对于推动有效的自助式分析和数据科学实践至关重要。如今&#xff0c;企业大都知道基于数据的决策是成功数字化转型的关键&#xff0c;但要做出有效的决策&#xff0c;只有可信的数据才能提供帮助&#xff0c;随着数据量和数据源的多样…...

(其他) 剑指 Offer 65. 不用加减乘除做加法 ——【Leetcode每日一题】

❓ 剑指 Offer 65. 不用加减乘除做加法 难度&#xff1a;简单 写一个函数&#xff0c;求两个整数之和&#xff0c;要求在函数体内不得使用 “”、“-”、“*”、“/” 四则运算符号。 示例: 输入: a 1, b 1 输出: 2 提示&#xff1a; a, b 均可能是负数或 0结果不会溢出 …...

RestTemplate 的用法

1.引入对应依赖 2.private final RestTemplate restTemplate; 3.上代码 Service Slf4j public class CspWarehouseServiceImpl implements ICspWarehouseService { private final RestTemplate restTemplate;public CspWarehouseServiceImpl() {this.restTemplate new Rest…...

postgresql-使用plpgsql批量插入用户测试数据

目的 使用plpgsql批量插入用户测试数据 ❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤我是分割线❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤ 我的环境 客户端&#xff1a;windows 版pgadmin4 服务端&#xff1a;linux版PostgreSQL 15.4 ❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤❤…...

通过Siri打造智能爬虫助手:捕获与解析结构化数据

在信息时代&#xff0c;我们经常需要从互联网上获取大量的结构化数据。然而&#xff0c;传统的网络爬虫往往需要编写复杂代码和规则来实现数据采集和解析。如今&#xff0c;在苹果公司提供的语音助手Siri中有一个强大功能可以帮助我们轻松完成这项任务——通过使用自定义指令、…...

【电源专题】典型设备的接地设计

在文章:【电源专题】接地的类型 中我们讲到不同的历史时期接地概念是不同的,有为了安全的电气接地和物理接地,也有为了提供参考电位的接地。 那么在设备接地的设计中,我们会怎么进行操作呢? 在文章【电源专题】接地的类型讲到一个混合接地的例子,我们可以把大功率的地接…...

成都公司做网站的/如何进行网络推广

第一部分 计算机基础知识部分习题一、选择题静态RAM的特点是A在不断电的条件下&#xff0c;信息在静态RAM中保持不变&#xff0c;故而不必定期刷新就能永久保存信息在不断电的条件下&#xff0c;信息在静态RAM中不能永久无条件保持&#xff0c;必须定期刷新才不致丢失信息在静态…...

随州seo/seo平台怎么样

完整团队 XP项目的所有参与者&#xff08;开发人员、业务分析师、测试人员等等&#xff09;一起工作在一个开放的场所中&#xff0c;他们是同一个团队的成员。这个场所的墙壁上随意悬挂着大幅的、显著的图表及其其他一些显示他们进度的东西。 计划游戏 计划是持续的、循序渐进…...

wordpress 免费插件/谈谈你对网络营销的看法

一、硬件材料 1*Arduino UNO R3开发板 1*光敏电阻 1*人体热释红外传感器 1*舵机模块 G90舵机 二、硬件接线图 CSDN 赤鱼科技...

北京怎么样做网站/网络营销的有哪些特点

集合&#xff1a;&#xff08;同数学概念&#xff09; 多个元素的无序组合 - 用{} 表示&#xff0c;元素间用逗号分隔 - 元素类型不必相同 - 每个元素唯一&#xff0c;不存在相同元素 - 元素不可更改&#xff0c;不能是可变数据类型 创建集合类型&#xff1a; {} 或 set()&…...

软件源码购买一般在哪个网站/保定网站推广公司

描述&#xff1a;LM2776DBVRLM2776 CMOS电容泵电压转换器可将2.7V至5.5V范围内的正电压转换&#xff0c;从而获得对应的等值负电压。 电感的转换器&#xff0c;解决了成本&#xff0c;尺寸和电磁干扰(EMI)多方面问题。在大多数负载条件下&#xff0c;LM2776的工作电流仅为100μ…...

做网站好的网站建设公司排名/沧州网站建设优化公司

环境&#xff1a;NAS型号&#xff1a;Synology RackStation 2418服务器&#xff1a;Centos7.4.1708 一&#xff1a;NAS上创建LUN*此处的IQN号需要复制记录下来&#xff0c;相当于NETAPP的WWN号二&#xff1a;linux上进行挂载yum install iscsi-initiator-utils -y 安装iscsi软件…...