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

Spring核心与设计思想、创建与使用

文章目录

  • 一、Spring是什么
  • 二、为什么要学习框架
  • 三、IoC和DI
    • (一)IoC
      • 1. 认识IoC
      • 2. Spring的核心功能
    • (二)DI
  • 四、Spring项目的创建
    • (一)使用 Maven 方式创建一个 Spring 项目
  • 五、Spring项目的使用
    • (一) 存储 Bean 对象到容器(Spring)中
    • (二)从 spring 将 bean 对象读取出来并使用
    • (三)getBean的更多用法
  • 六、Spring更简单的存储和读取对象的方式
    • (一)存储 Bean 对象
    • (二)读取 Bean 对象
      • 1. 属性注入
      • 2. 构造方法注入
      • 3. Setter 注入
      • 4. 使用 @Resource 代替 @Autowired
      • 5. 问题一:@Resource VS @Autowired
      • 6. 问题二:属性注入、构造方法注入与set方法注入有什么区别
      • 7. 问题三:当我们使用 @Bean 保存了多个相同类的不同对象,此时上述代码就会出现问题,会报出不唯一的异常
  • 七、Bean 作用域和生命周期
    • (一)Bean 作用域的问题
      • 1. 案例
      • 2. 原因分析
    • (二)作用域的定义
      • 1. Bean 的六种作用域
      • 2. 设置作用域
    • (三)Spring 执行流程和 Bean 的生命周期
      • 1. Spring 执行流程
      • 2. Bean 生命周期

一、Spring是什么

  我们通常所说的 Spring 指的是 Spring Framework(Spring 框架),它是⼀个开源框架。Spring ⽀持⼴泛的应⽤场景,它可以让 Java 企业级的应⽤程序开发起来更简单
  ⽤⼀句话概括 Spring:Spring 是包含了众多⼯具⽅法的 IoC 容器

二、为什么要学习框架

  1. 就像我们装修房子,不使用框架就像我们材料自己买,关于房子的事情都需要亲力亲为,使用框架时就像我们请了装修公司,材料、人员安排等等我们不再关系,而只需要提出需求,跟进进度即可,特点就是高效
  2. 框架更加易用,并且使用起来也是非常简单

  上述优势通过 SpringBoot 和 Servlet 对比能够更容易地看出:

  1. SpringBoot 添加外部 jar 包更容易,不易出错,直接引入即可,而Servlet还需要关注版本问题
  2. 调试、发布项目更加方便,无需配置 Tomcat,因为它里面已经内置了
  3. 添加路由更加方便,无需每个访问地址都添加一个类

三、IoC和DI

(一)IoC

  在认识IoC之前,我们要先知道容器地概念,通过百度,我们可以知道容器是用来容纳某种物品的装置,我们之前学过的List是数据存储容器,Tomcat是Web容器

1. 认识IoC

  首先明确一点,Spring也是一个容器,它是一个IoC容器
什么是 IoC?

  IoC = Inversion of Control 翻译成中⽂是“控制反转”的意思,IoC就是控制反转的思想。“控制反转”是两个词,控制和反转。指的是:之前程序的控制权限是在我们自己手上,现在把控制权交出去,我们只需要使用即可

  1. 一般情况下,我们在 A 类 中,想去调用 B 类中的方法,要去 new B 类对象,通过 对象 去调用 B类中的方法。当前 B 的控制权,是我们手上的
  2. 而控制反转,就是将我们手上的权限,交由 Spring 框架来操作
  3. 此时,我们想要 A 类中调用 B 的时候,告诉框架,我要在 A 中调用 B 了。至于 B 的生命周期,和我们没有任何关系。
  4. 因为我们把控制权 “反转给了” Spring 框架。Spring 会帮我们管理所有的对象(Bean)

2. Spring的核心功能

  通过上述关于IoC的介绍,我们知道了Spring的核心功能就是两点:

  1. 将 Bean(对象)存储到 Spring(容器)中
  2. 将 Bean(对象)从 Spring(容器)中取出来

(二)DI

  只要我们说到IoC,就离不开DI,它们俩的关系就像是切菜和菜刀一样,切菜是一种动作,也是一种想法,该如何实现呢?利用菜刀来实现这个想法
  DI 是 Dependency Injection 的缩写,翻译成中⽂是“依赖注⼊”的意思。具体解释就是在 IoC 容器运行期间,动态的将某种依赖关系注入到对象中。就是为了实现 IoC 的思想,所以,IoC 和 DI 的核心都是为了“控制反转”,,但是区别就是IoC是思想,DI是实现

四、Spring项目的创建

(一)使用 Maven 方式创建一个 Spring 项目

  1. 创建一个普通的 Maven 项目(不需要添加web-app模板)
  2. 添加 Spring 框架支持
    (1)在 pom.xml 当中加入依赖
    <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>
    
    (2)粘贴完之后,刷新 Maven
  3. 在 Java 源文件中添加一个启动类,并编写 main 方法即可
    添加启动类 & 编写main方法

五、Spring项目的使用

(一) 存储 Bean 对象到容器(Spring)中

  1. 如果第一次存储,先在 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 http://www.springframework.org/schema/beans/spring-beans.xsd"></beans>
    
  2. 创建 Bean 对象(Java对象的另一种称呼),和对普通的类实例化一样
    创建bean对象
  3. 在配置文件中将需要保存到容器中的 Bean 对象进行注册,如下图所示,表示将 User 对象以类似字典的形式存入到 Spring 当中,id就是它的标识(通常使用小驼峰),类似于 HashMap 中的key
    注册

(二)从 spring 将 bean 对象读取出来并使用

  1. 得到 spring 上下文对象
  2. 通过上下文对象提供的方法获取自己需要使用的 bean 对象
  3. 使用 bean 对象

从 spring 将 bean 对象读取出来并使用

  除了图上通过 ApplicationContext 来获取 spring 上下文,我们也可以通过 BeanFactory (Bean工厂)来作为 spring 的上下文,代码如下

BeanFactory beanFactory = new XmlBeanFactory(new ClassPathResource("spring-config.xml"));

  那么这二者有什么区别呢,这就是一个经典面试题:ApplicationContext VS BeanFactory

相同点:都可以实现从容器中获取bean,都提供了 getBean 方法
不同点:

  1. ApplicationContext 属于 BeanFactory 的子类。BeanFactory 只提供了基础访问 Bean 的方法,而 ApplicationContext 除了拥有 BeanFactory 的所有功能之外,还提供了更多的方法实现,比如对国际化的支持、资源访问的支持、以及事件和传播等方面的支持
  2. 性能方面来说二者不同。BeanFactory 是按需加载 Bean,懒加载;ApplicationContext 是饿汉方式,在创建时会将所有的 Bean 加载起来,以备以后使用

(三)getBean的更多用法

  1. 使用 bean name 获取 bean
User user = (User)context.getBean("user");
  1. 根据 bean type 获取 bean
User user = context.getBean(User.class);

  这个写法虽然简单,但是存在问题,如果两个类对象类名相同,但包不同,同时保存到了 spring 中,那么此时再通过这种方法进行获取 bean ,就会报出类不唯一的异常
3. 根据 bean name 和 bean type 获取 bean

User user = context.getBean("user", User.class);

  这种写法和第一种比较看似只是不用强转,但是如果返回的 bean 是 null,此时进行强转就会直接抛出空引用异常,而第三种方法不会存在这个问题,因此这种写法要比第一种更加健壮,所以更加推荐这种写法

六、Spring更简单的存储和读取对象的方式

  上述存储和读取 bean 对象的方式只是最原始的方式,仍然不够简洁和方便;而在 Spring 中,想要更简单的存储和读取对象的核心是使用注解,这也就是我们下来要介绍的内容

(一)存储 Bean 对象

  我们之前存储 bean 时,是通过在配置文件中添加一行 bean 注册内容,而现在我们只需要一个注解就可以替代之前的操作,不过在此之前,我们要先进行一些准备工作

  1. 前置工作:配置扫描路径(关键
    在 spring 配置文件中设置 bean 的扫描根路径

    <?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:content="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"><content:component-scan base-package="com.beans"></content:component-scan>
    </beans>
    

    注意:在标签中,base-package表示的就是扫描根路径,这个路径是我们自己设置的,而我们以后要存储的类,都会写入到这个路径的包/子包底下,只要在这个包底下的类加了注解,就表示存储到 spring 中了

  2. 简单的将 bean 存储到容器中

    1. 使用五大类注解实现
      1. Controller(控制器)
        // 必须添加注解
        @Controller
        public class UserController {public void hello() {System.out.println("hello, UserController!");}
        }
        
      2. Service(服务)
      3. Repository(仓库)
      4. Configuration(配置)
      5. Component(组件)
    2. 通过 @Bean 方法注解实现
      注意,@Bean 注解只能添加到方法上,而不能添加到类上;@Bean必须搭配五大类注解使用;读取时 bean name 不是类名,而是方法名(要求:必须完全一致,不再是之前五大类注解的规则)(不一定,可以参考下方第六点)
      // 使用
      // 注意这里的 bean name 是方法名,不是类名
      User user = context.getBean("GetUser", User.class);
      System.out.println(user);// 保存
      @Component
      public class UserBeans {/*** 注意:只使用一个 @Bean 是无法将对象存储到容器中的* 必须在类上也搭配一个五大类注解,这样做的目的是为了提高效率* @return*/@Beanpublic User GetUser() {User user = new User();user.id = 1;user.name = "张三";return user;}
      }
      
  3. 提出疑问:上述将 bean 存储到容器中,明明五大类注解任何一个都可以,为什么还需要五大类注解?
    解答:
      这里就涉及到软件工程的知识了,如下图所示,我们的五大类注解和下面的软件架构分层一一对应,当我们的 bean 很多时,我们就有必要根据不同的功能使用不同的注解对不同的 bean 进行区分,让代码的可读性提高,让程序猿能够直观的判断当前类的用途。Component 就是用于当 bean 不属于下面四种情况时,作为一个工具来使用时使用 Component 来注释
    软件架构分层

  4. 五大类注解之间的关系,这个问题我们可以直接看底层源码,就会发现其他四个类注解都是继承自 Component,换句话说,Compinent 是其他四个类的父类,以 Controller 为例
    五大注解继承关系

  5. 使用五大类注解产生的 bean name 问题。我们读取 bean 时,这个问题是避不开的,因此需要我们着重注意
    解答:
      这个问题我们需要去看注解 bean name 生成器,即:AnnotationBeanNameGenerator,当我们在这个方法中左拐右拐,最终却定位到了decapitalize.java文件,通过查看文件目录结构,我们发现,这个方法是在 jdk 里自带的,换句话说,通过注解生成 bean name 的规则,实际是 jdk 自带的,接下来我们对这个方法进行源码分析,如下图:
    bean name生成规则
      因此我们说,当类名第一个字符和第二个字符都是大写时,bean name 就是它本身,否则就是第一个字符小写

  6. 使用 @bean 的时候,我们想要读取 Bean 对象,只能使用方法名吗,答案是不一定,我们可以人为的给这个方法返回的 bean 设置一个 name,甚至可以给他起多个 name ,如下方代码

    // 如果只有一个 name ,不需要加"{}"
    @Bean(name = {"userInfo", "user1"})
    public User GetUser() {User user = new User();user.id = 1;user.name = "张三";return user;
    }
    

    注意,在这种情况下方法名将无法再使用

(二)读取 Bean 对象

  获取 bean 对象也叫做对象装配,是把对象取出来放到某个类中,有时候也叫对象注⼊。对象注入的实现方式有三种:

  1. 属性注入
  2. 构造方法注入
  3. Setter 注入

三种对象注入都可以通过 @Autowired 实现

1. 属性注入

下面我们将 UserService 类注入到 UserController2 类中

// 将 UserService 注入到 UserController2
@Controller
public class UserController2 {@Autowiredprivate UserService userService;public void hello() {userService.hello();}
}// 将 UserController2 注入到 App 中并执行
public class App {public static void main(String[] args) {ApplicationContext context =new ClassPathXmlApplicationContext("spring-config.xml");UserController2 userController2 =context.getBean("userController2", UserController2.class);userController2.hello();}
}

运行结果
Autowired属性注入

2. 构造方法注入

我们通过构造方法和@Autowired将 UserService 类注入到 UserController3 类中,如果当前类中只有一个构造方法,@Autowired可以省略

@Controller
public class UserController3 {private UserService userService;//只有一个构造方法时可以省略@Autowiredpublic UserController3(UserService userService) {this.userService = userService;}public void hello() {userService.hello();}
}public class App {public static void main(String[] args) {ApplicationContext context =new ClassPathXmlApplicationContext("spring-config.xml");UserController3 userController = context.getBean(UserController3.class);userController.hello();}
}

运行结果
构造方法注入 Bean 对象

3. Setter 注入

为需要注入的类提供一个set方法

@Controller
public class UserController4 {private UserService userService;@Autowiredpublic void setUserService(UserService userService) {this.userService = userService;}public void hello() {userService.hello();}
}public class App {public static void main(String[] args) {ApplicationContext context =new ClassPathXmlApplicationContext("spring-config.xml");UserController4 userController4 = context.getBean(UserController4.class);userController4.hello();}
}

运行结果
Setter注入

4. 使用 @Resource 代替 @Autowired

  @Resource 是 Java 官方提供的,@Autowired 是由 Spring 官方提供的,直接将 @Resource 替换为 @Autowired 即可。但是,@Resource 不支持属性注入因此我们说,注入方式有三种,注入方法有这两种

5. 问题一:@Resource VS @Autowired

相同点:都可以实现将一个对象注入到类当中
不同点:

  1. 实现者不同,@Resource是 Java 官方提供的,@Autowired是 Spring 官方提供的
  2. 用法不同:@Autowired 支持属性注入、构造方法注入和Setter注入,但是 @Resource 不支持属性注入
  3. 支持参数不同:@Resource 支持更多的参数设置,比如name、type设置,而 @Autowired 只支持 required 参数设置

6. 问题二:属性注入、构造方法注入与set方法注入有什么区别

答:
  1. 属性注入写法简单,但只能运行在IoC容器下,其他容器会出现问题
  2. Setter注入:早期 Spring 版本推荐的写法,但 Setter 注入没有构造方法注入通用,其他语言写set方法很麻烦
  3. 构造方法注入:通用性更好,它能确保在使用注入对象之前,此注入对象一定初始化过了

7. 问题三:当我们使用 @Bean 保存了多个相同类的不同对象,此时上述代码就会出现问题,会报出不唯一的异常

如下图:
多次保存问题
多次保存问题
  针对这个问题,我们有如下的解决方案:

  1. 精确的描述 bean 的名称(将注入的名称写对)

解决方案一

  1. 使用 @Resource 设置 name 的方式来重命名注入对象

Resource注解

  1. 如果工作时要求不能使用 @Resource,并且我们业务代码已经写了很多,采用第一种方法改起来很麻烦,我们就可以使用 @Qualifier + @Autowired 来筛选 bean 对象

Qualifier的使用

七、Bean 作用域和生命周期

(一)Bean 作用域的问题

1. 案例

  由上述知识我们知道,Spring 是用来读取和存储 Bean 的,因此 Bean 是 Spring 最核心的操作资源,因此我们需要更深入的了解一下 Bean。其中我们的预期结果是公共的 Bean 经过注入之后可以在各自的类进行修改,但是不能影响到其他的类但是经过测试发现结果并不是这样

  1. 测试类1,注入对象后将将象的 name 设为“王五”,并返回
    测试类1
  2. 测试类2,注入对象后直接返回
    测试类2
  3. 结果
    测试结果

  注意,作者在测试这里的代码时,恰好遇到了一个需要注意的问题,在有 Spring 存在的项目中,Spring 的注入要统一使用,类的一步步引用,要么为全部注入,要么都不注入,否则会出错。代到当前测试例子中,由于作者刚开始进行测试时在 app 类中两个类都是 new 出来的,导致两个类中并没有对 User 类进行注入,在操作时就会报出空指针异常
  言归正传,我们在上面进行测试时,发现结果和预期并不相同,UserTestBean2中对对象进行了修改,居然影响到了UserTestBean1,那么问题是什么呢?

2. 原因分析

  上述问题的原因就是因为 Bean 默认情况下是单例模式(singleton),换句话说所有类使用的是同一个对象,这样做可以很大程度上提高性能

(二)作用域的定义

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

1. Bean 的六种作用域

Spring 容器在初始化一个 Bean 的实例时,同时会指定该实例的作用域。Spring 有六种作用域,最后四种是基于 Spring MVC 生效的:

  1. singleton:单例作用域(Spring默认选择该作用域)
  2. prototype:原型作用域(多例作用域)
  3. request:请求作用域
  4. session:会话作用域
  5. application:全局作用域
  6. websocket:HTTP WebSocket 作用域

使用场景

  1. singleton:通常无状态的 Bean 使用该作用域。无状态表示 Bean 对象的属性状态不需要更新
  2. prototype:通常有状态(即需要进行修改)的 Bean 使用该作用域
  3. request:一次http的请求和相应的共享Bean
  4. session:用户会话的共享Bean,比如记录一个用户的登录信息
  5. application:Web应用的上下文信息,比如:记录一个应用的共享信息
  6. websocket:Websocket的每次会话中,保存了一个Map结构的头信息,将用来包裹客户端消息头,第一次初始化后,直到 WebSocket 结束都是同一个Bean

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

  1. singleton 是 Spring Core 的作用域;application 是 Spring Web 中的作用域
  2. singleton 作用于 Ioc 的容器,而 application 作用于 Servlet 容器

2. 设置作用域

  使用 @Scope 标签就可以用来声明 Bean 的作用域。@Scope 标签既可以修饰方法也可以修饰类,@Scope 有两种设置方式:

  1. 直接设置值:@Scope(“prototype”)
  2. 使用枚举设置:@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)

示例:

// @Scope("prototype")
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
@Bean(name = "user2")
public User getUser2() {User user = new User();user.setId(2);user.setName("李四");return user;
}

(三)Spring 执行流程和 Bean 的生命周期

1. Spring 执行流程

  1. 启动 Spring 容器
  2. 根据配置完成 Bean 初始化(分配内存空间)
  3. 注册 Bean 对象到容器中
  4. 装配 Bean 到需要的类中

2. Bean 生命周期

  1. 实例化 Bean (为 Bean 分配内存空间)
  2. 设置属性(Bean 注入和装配)
  3. Bean 初始化
  • 实现了各种 Aware 通知的方法
  • 执行初始化的前置方法,依赖注入操作之后被执行
  • 执行构造方法,两种执行方式,一种是执行 @PostConstruct(优先,注解时代的产物),另一种是执行 init-method 方法(xml时代的产物)
  • 执行初始化的后置方法
  1. 使用 Bean
  2. 销毁 Bean

(1)@PreDestroy
(2)重写 @DisposableBean 接口方法
(3)destroy-method

注意:步骤二与步骤三顺序不能交换,因为在步骤三中的构造方法中可能会用到注入对象的方法

相关文章:

Spring核心与设计思想、创建与使用

文章目录 一、Spring是什么二、为什么要学习框架三、IoC和DI&#xff08;一&#xff09;IoC1. 认识IoC2. Spring的核心功能 &#xff08;二&#xff09;DI 四、Spring项目的创建&#xff08;一&#xff09;使用 Maven 方式创建一个 Spring 项目 五、Spring项目的使用&#xff0…...

mysql 备份 还原

1:备份 执行命令方案1: /usr/local/mysql/bin/mysqldump -uX -pX -h 127.0.0.1 --set-gtid-purgedOFF --skip-extended-insert --add-drop-table --add-locks --create-options --disable-keys --lock-tables --quick --set-charset -e --max_allowed_packet16777216 --net_b…...

每日学术速递4.26

CV - 计算机视觉 | ML - 机器学习 | RL - 强化学习 | NLP 自然语言处理 Subjects: cs.CV 1.AutoNeRF: Training Implicit Scene Representations with Autonomous Agents 标题&#xff1a;AutoNeRF&#xff1a;使用自主代理训练隐式场景表示 作者&#xff1a;Pierre Marz…...

RabbitMQ使用StringRedisTemplate-防止重复消费

造成重复消费的原因&#xff1a; MQ向消费者推送message&#xff0c;消费者向MQ返回ack&#xff0c;告知所推送的消息消费成功。但是由于网络波动等原因&#xff0c;可能造成消费者向MQ返回的ack丢失。MQ长时间&#xff08;一分钟&#xff09;收不到ack&#xff0c;于是会向消…...

临沂大学张继群寄语

目录 寄语 1、不能有不良睹好 2、坚毅的个性和勤奋的品质 3、会存钱...

线程学习笔记

1:Thread 线程的生命周期控制 2:Runnable 可执行的任务和程序 3:Callable 执行程序后返回结果 4:Future 收集程序返回结果 5:Executor 线程池 6:ForkJoin 默认线程池 每个线程有工作队列 工作窃取 7:RunnableFuture FutureTask 实现 Runnable 和 Future 执…...

代码随想录算法训练营第四十二天|01背包问题,你该了解这些!、01背包问题,你该了解这些! 滚动数组 、416. 分割等和子集

文章目录 01背包问题&#xff0c;你该了解这些&#xff01;01背包问题&#xff0c;你该了解这些&#xff01; 滚动数组416. 分割等和子集 01背包问题&#xff0c;你该了解这些&#xff01; 题目链接&#xff1a;代码随想录 二维数组解决0-1背包问题 解题思路&#xff1a; 1.dp…...

结构体指针、数组指针和结构体数组指针

结构体指针 首先让我们定义结构体&#xff1a; struct stu { char name[20]; long number; float score[4]; }; 再定义指向结构体类型变量的指针变量&#xff1a; struct stu *student; /*定义结构体类型指针*/ student malloc(sizeof(struct stu)); /*为指针变量分…...

项目架构一些注意点

考虑系统的 稳定性 一、微服务的稳定性 1、如何解决那些不稳定的因素/问题&#xff1f;也是常说的如何容错。 2、一个系统的高可用取决于它本身和其强依赖的组件的高可用 3、消除单点 保活机制 健康检查 注册中心如何保障稳定性 注册中心集群 微服务本身对注册信息的本地持…...

Forefront GPT-4免费版:开启无限畅聊时代,乐享人工智能快感,无限制“白嫖”,还能和N多角色一起聊天?赶紧注册,再过些时间估计就要收费了

目录 前言注册登录方式应用体验聊天体验绘图体验 “是打算先免费后收费吗&#xff1f;”建议其它资料下载 前言 近期&#xff0c;人工智能技术迎来重大飞跃&#xff0c;OpenAI的ChatGPT等工具成为全球数亿人探索提高生产力和增强创造力的新方法。人们现在可以使用人工智能驱动…...

深入浅出 Compose Compiler(1) Kotlin Compiler KCP

前言 Compose 的语法简洁、代码效率非常高&#xff0c;这主要得益于 Compose Compiler 的一系列编译期魔法&#xff0c;帮开发者生成了很多样板代码。但编译期插桩也阻碍了我们对于 Compose 运行原理的认知&#xff0c;想要真正读懂 Compose 就必须先了解它的 Compiler。本系列…...

BatchNormalization和LayerNormalization的理解、适用范围、PyTorch代码示例

文章目录 为什么要NormalizationBatchNormLayerNormtorch代码示例 学习神经网络归一化时&#xff0c;文章形形色色&#xff0c;但没找到适合小白通俗易懂且全面的。学习过后&#xff0c;特此记录。 为什么要Normalization 当输入数据量级极大或极小时&#xff0c;为保证输出数…...

大数据 | 实验二:文档倒排索引算法实现

文章目录 &#x1f4da;实验目的&#x1f4da;实验平台&#x1f4da;实验内容&#x1f407;在本地编写程序和调试&#x1f955;代码框架思路&#x1f955;代码实现 &#x1f407;在集群上提交作业并执行&#x1f955;在集群上提交作业并执行&#xff0c;同本地执行相比即需修改…...

Java文档注释-JavaDoc标签

标签含义author指定作者{code}使用代码字体以原样显示信息&#xff0c;不处理HTML样式deprecated指定程序元素已经过时{docRoot}指定当前文档的根目录路径exception标识由方法或构造函数抛出的异常{inheritDoc}从直接超类中继承注释{link}插入指向另外一个主题的内联链接{linkp…...

黑盒测试过程中【测试方法】详解5-输入域,输出域,猜错法

在黑盒测试过程中&#xff0c;有9种常用的方法&#xff1a;1.等价类划分 2.边界值分析 3.判定表法 4.正交实验法 5.流程图分析 6.因果图法 7.输入域覆盖法 8.输出域覆盖法 9.猜错法 黑盒测试过程中【测试方法】讲解1-等价类&#xff0c;边界值&#xff0c;判定表_朝一…...

Python学习之sh(shell脚本)在Python中的使用

文章目录 前言一、sh是什么&#xff1f;二、使用步骤1.安装2.使用示例3.使用sh执行命令4.关键字参数5.查找命令6.Baking参数 前言 本文章向大家介绍[Python库]分析一个python库–sh&#xff08;系统调用&#xff09;&#xff0c;主要内容包括其使用实例、应用技巧、基本知识点…...

追求卓越:编写高质量代码的方法和技巧

本文讨论了编写高质量代码的重要性&#xff0c;并详细介绍了高质量代码的特征、编程实践技巧和软件工程方法论。通过遵循这些原则和实践&#xff0c;程序员可以编写出更稳定、可维护和可扩展的代码。 一、 前言 写出高质量代码是每个程序员的追求和目标。高质量的代码可以使程…...

MATLAB算法实战应用案例精讲-【人工智能】机器视觉(概念篇)(最终篇)

目录 前言 几个高频面试题目 如何评价一个光源的好坏? 如何依靠光源增强图像对比度?...

【老王读SpringMVC-3】根据 url 是如何找到 controller method 的?

前面分析了 request 与 handler method 映射关系的注册&#xff0c;现在再来分析一下 SpringMVC 是如何根据 request 来获取对应的 handler method 的? 可能有人会说&#xff0c;既然已经将 request 与 handler method 映射关系注册保存在了 AbstractHandlerMethodMapping.Ma…...

人机交互到艺术设计及玫瑰花绘制实例

Python库之图形用户界面 Riverbank Computing | Introduction Welcome to wxPython! | wxPython Overview — PyGObject Python库之游戏开发 https://www.pygame.org/news Panda3D | Open Source Framework for 3D Rendering & Games python.cocos2d.org Python库之…...

多臂老虎机问题

1.问题简介 多臂老虎机问题可以被看作简化版的强化学习问题&#xff0c;算是最简单的“和环境交互中的学习”的一种形式&#xff0c;不存在状态信息&#xff0c;只有动作和奖励。多臂老虎机中的探索与利用&#xff08;exploration vs. exploitation&#xff09;问题一直以来都…...

DNS 查询原理详解

DNS&#xff08;Domain Name System&#xff09;是互联网上的一种命名系统&#xff0c;它将域名转换为IP地址。在进行DNS查询时&#xff0c;先要明确需要查询的主机名&#xff0c;然后向本地DNS服务器发出查询请求。 1. 本地DNS服务器查询 当用户在浏览器中输入一个URL或者点…...

浅谈软件测试工程师的技能树

软件测试工程师是一个历史很悠久的职位&#xff0c;可以说从有软件开发这个行业以来&#xff0c;就开始有了软件测试工程师的角色。随着时代的发展&#xff0c;软件测试工程师的角色和职责也在悄然发生着变化&#xff0c;从一开始单纯的在瀑布式开发流程中担任测试阶段的执行者…...

转型产业互联网,新氧能否再造辉煌?

近年来&#xff0c;“颜值经济”推动医美行业快速发展&#xff0c;在利润驱动下&#xff0c;除了专注医美赛道的企业之外&#xff0c;也有不少第三方互联网平台正强势进入医美领域&#xff0c;使以新氧为代表的医美企业面对不小发展压力&#xff0c;同时也展现出强大的发展韧性…...

CRE66365 应用资料

CRE66365是一款高度集成的电流模式PWM控制IC&#xff0c;为高性能、低待机功耗和低成本的隔离型反激转换器。在正常负载条件下&#xff0c;AC输入高电压下工作在QR模式。为了最大限度地减少开关损耗&#xff0c;QR 模式下的最大开关频率被内部限制为 77kHz。当负载较低时&#…...

vue3快速上手学习笔记,还不快来看看?

Vue3快速上手 1.Vue3简介 2020年9月18日&#xff0c;Vue.js发布3.0版本&#xff0c;代号&#xff1a;One Piece&#xff08;海贼王&#xff09;耗时2年多、2600次提交、30个RFC、600次PR、99位贡献者github上的tags地址&#xff1a;https://github.com/vuejs/vue-next/release…...

HDU 5927 Auxiliary Set

原题链接&#xff1a; https://acm.hdu.edu.cn/showproblem.php?pid5927 题意&#xff1a; 有一颗根节点是1的树&#xff0c;其中有重要的点和不重要的点&#xff0c;重要的点需满足以下两个条件至少一个&#xff1a; 1.本来就是重要的点 2.是两个重要的点的最近共同祖先 有t…...

24:若所有参数皆需类型转换,请为此采用non-member函数

令class支持隐式类型转换通常是个糟糕的主意。 这条规则有其例外&#xff0c;最常见的例外是在建立数值类型时。 例&#xff0c;假设你设计一个class用来表现有理数&#xff0c;则允许整数“隐式转换”为有理数就很合理。 class Rational{ public:Rational(int numerator0,i…...

CMake(2)-详解-编译-安装-支持GDB-添加环境检查-添加版本号-生成安装包

目录 1.什么是CMake 1.1 编译流程CMakeLists.txt a) 最简单 demo1 b) 常用demo2 c) 单目录&#xff0c;源文件-输出文件 DIR_SRCS中 d)多目录&#xff0c;多源文件 1.2.执行命令&#xff1a; 1.3.自定义编译选项 2.安装和测试 3.支持GDB 4.添加环境检查 5.添加…...

java面试题(redis)

目录 1.redis主要消耗什么物理资源&#xff1f; 2.单线程为什么快 3.为什么要使用Redis 4.简述redis事务实现 5.redis缓存读写策略 6.redis除了做缓存&#xff0c;还能做些什么&#xff1f; 7.redis主从复制的原理 8.Redis有哪些数据结构&#xff1f;分别有哪些典型的应…...