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

spring 笔记

一、spring概述

 

1.1 spring介绍

spring是一个轻量级的控制反转和面向切面的容器框架,用来解决企业项目开发的复杂度问题---解耦

  • 轻量级:体积小,对代码没有侵入性
  • 控制反转:IOC inverse of control, 把创建对象的工作交由spring完成,spring在创建对象的同时可以完成对象属性的赋值(DI)
  • 面向切面:AOP aspect oriented programming 面向切面编程,可以在不改变原有业务逻辑的情况下实现对业务的增强
  • 容器:实例的容器,管理创建的对象

1.2 spring架构简介

image-20220802084037659

1.2.1 core container

spring的容器组件,用于完成实例的创建和管理

  • core 容器组件的核心
  • beans 实例对象的管理
  • context 容器上下文

1.2.2 AOP Aspects

spring的AOP组件,实现面向切面编程

  • aop 
  • aspects

1.2.3 WEB

Spring web组件,实际指的是springMVC框架,实现web项目的MVC控制

  • web ---spring 对web项目的支持
  • webmvc --- springMVC

1.2.4 Data Access 

spring 数据访问组件,也是一个基于JDBC封装的持久层框架(即使没有mybatis,spring也可以完成持久化操作)

  • transactions  事务管理

1.2.5 test

spring的单元测试组件,提供了spring环境下的单元测试支持。

二、Spring IOC --- 基于XML

spring ioc 容器组件,可以完成对象的创建,对象属性赋值,对象的管理

2.1 spring框架部署(IOC相关)

  1. 创建maven工程
  2. 添加springIOC依赖
    1. core
    2. beans
    3. context --- 其实只导入这一个就行了,因为其他的依赖也会一起导入
  3. 创建spring配置文件
    1. 配置文件来“告诉”spring容器创建什么对象,给对象属性怎么赋值
    2. resources目录下创建名为applicationContext.xml文件(文件名可以自定义,需要定义一些规则,可以创建一个模板)
spring 依赖
<!--
<dependency><groupId>org.springframework</groupId><artifactId>spring-core</artifactId><version>5.2.10.RELEASE</version>
</dependency>
<dependency><groupId>org.springframework</groupId><artifactId>spring-beans</artifactId><version>5.2.10.RELEASE</version>
</dependency>
-->
<dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.2.10.RELEASE</version>
</dependency>

2.2 springIOC的使用 :创建并管理对象

  1. 创建do实体类,如Student类
  2. applicationContext.xml文件中配置bean标签
  3. 初始化spring容器,加载spring配置文件,获取实例对象
只完成实例的创建,但是属性没有值
<bean id="studentDo唯一标识" name="dao" class="Student的全限定名"/>完成实例的创建,同时给name属性赋值
<bean id="studentDo唯一标识" name="dao" class="Student的全限定名"><property name="stuName" value="zhangsan" />
</bean>

public static void main(String[] args) {ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");//此处根据bean标签的id属性和name属性的任意一个值来获取bean对象// 创建出来student对象,但是属性没有值Student Student1 = (Student) ctx.getBean("studentDo"); 
}

2.3 IOC和DI 

  • IOC inverse of control控制反转,当我们需要通过spring完成对象的创建时,需要将这个类交给spring进行管理 ---- 通过配置bean标签,spring反射
  • DI dependency injection 依赖注入,通过spring容器,给创建的对象属性赋值

2.4 DI 

2.4.1 依赖注入的方式 --- 反射

spring容器加载配置文件后,通过反射创建类的对象,并给属性赋值。通过反射实现属性注入有以下几种方式:

  • set方法注入
  • 构造器注入
  • 接口注入(不常用。。。)

2.4.2 set注入

在bean标签中通过配置property标签给属性赋值,实际就是通过set方法进行注入

  • 简单类型及字符串 ----> 直接通过property标签的value属性进行赋值
  • 引用类型   
    • ----> 使用property标签ref属性注入引用类型对象
    • ----> 在property标签里面创建bean标签
  • 集合类型
    • list 
      • list<简单类型封装类或者字符串>, 可以在property 的value里面直接赋值 逗号隔开
      • list<引用类型>  见下面
    • set ---和list一样,就是把list标签变成set
    • map
<bean id="bookService" class="com.itheima.service.impl.BookServiceImpl"><property name="bookDao" ref="bookDao"/>
</bean>
<bean id="bookDao" class="com.itheima.dao.imipl.BookDaoImpl"/>-------<bean id="bookService" class="com.itheima.service.impl.BookServiceImpl"><property name="bookDao"><bean id="bookDao" class="com.itheima.dao.imipl.BookDaoImpl"/></property>
</bean>--------
list 依赖注入1
<property name="hobbies" value="唱,跳,rap">---------
list 依赖注入2
<property name="hobbies"><list><value>唱</value><value>跳</value><value>rap</value></list>
</property>---------
list 依赖注入3<property name="hobbies"><list><bean id="book" class="com.itheima.Book"/><bean id="book" class="com.itheima.Book"/><bean id="book" class="com.itheima.Book"/></list>
</property>---------
list 依赖注入4<property name="hobbies"><list><ref id="book"/><ref id="book"/></list>
</property><bean id="book" class="com.itheima.Book"/>---------
map<property name="card"><map><entry  key="身份证" value="123712739171293"></entry><entry  key="银行卡" value="234234234324344"></entry></map>
</property>

2.4.3 构造器注入

  • 简单类型和字符串
    • 1、定义有参构造器,2、使用constructor-arg标签,index值为第几个参数,value为要注入的值
  • 对象类型
  • 集合类型
<bean id="bookDao" class="com.itheima.dao.impl.BookDaoImpl"><constructor-arg name="databaseName" index="0" value="mysql"/><constructor-arg name="connectionNum" index="1" value="666"/>
</bean><bean id="bookService" class="com.itheima.service.impl.BookServiceImpl"><constructor-arg name="bookDao" ref="bookDao"/><constructor-arg name="userDao" ref="userDao"/>
</bean>

2.5 ioc- bean的作用域

同一个bean_id ,通过配置scope 的值来指定对象的作用域

  • singleton ---单例模式  默认的值,默认饿汉模式,初始化阶段就会完成实例的创建
  • prototype ---多例模式
<bean id="book" class="book的全限定名" scope="" lazy-init=""/>
scope 有两个取值
singleton ---单例模式  默认的
prototype ---多例模式lazy-init默认取值false,饿汉模式,设置为true可以改为懒汉模式

2.6 bean 的生命周期

bean标签中可以

  • 通过init-method属性指定当前bean的初始化方法,在构造器执行之后执行
  • 通过destroy-method指定当前bean的销毁方法,在对象销毁之前执行

2.7 自动装配

spring在实例化当前bean时,重spring自己的容器中找到匹配的实例赋值给当前bean的属性,通过bean标签中的autowire进行配置

  • byName:根据当前bean的属性名, 在spring容器中寻找名称匹配的对象(bean中的属性名称和spring容器中其他bean的id 进行比较,有可能导致类型不一致)
  • byType:根据当前bean的属性类型,在spring容器中寻找类型匹配的对象 (要是配置了两个不同id的bean,也会报错)

2.8 ioc的工作原理

三、Spring IOC --- 基于注解

3.1 spring框架部署

3.1.1 创建maven项目

3.1.2添加springIOC依赖

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

3.1.3 创建spring配置文件,声明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"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:annotation-config/><!-- 声明Spring工厂注解的扫描范围 --><context:component-scan base-package="com.qfedu.beans"/></beans>

3.2 IOC的常见注解

3.2.1 @Component

  • 类注解,声明此类被spring容器进行管理,相当于bean标签
  • @Component(value=“stu”)value属性的值相当于bean标签中的id,可以省略,如果省略则当前类的id默认为类名首字母改小写
  • 除了@Component, @Service、@Controller、@Repository这三个注解也可以将类声明给Spring管理,他们主要是语义上的区别
    • @Controller 注解主要声明将控制器类配置给Spring管理,例如Servlet
    • @Service 注解主要声明业务处理类配置Spring管理,Service接口的实现类
    • @Repository 直接主要声明持久化类配置给Spring管理,DAO接口

3.2.2 @Scope

  • 类注解,用于声明当前类是否是单例模式,相当于bean标签的scope属性
  • @Scope("prototype") 表示声明当前类为非单例模式(默认单例模式)

3.2.3 @Lazy

  • 类注解,用于声明一个单例bean,是否为懒汉模式
  • 默认为饿汉模式,@Lazy(true) 表示声明为懒汉模式

3.2.4 @PostConstruct

  • 方法注解,声明一个方法为当前类的初始化方法(在构造器之后执行),相当于bean标签的init-method属性

3.2.5 @PreDestory

  • 方法注解,声明一个方法为当前类的销毁方法(在对象从容器中释放之前执行),相当于bean标签的destory-method属性

3.2.6 @Autowoired

  • 属性注解,声明当前属性自动装配,默认为byType
  • @Autowired(required = false) 通过requried属性设置当前自动装配是否为必须(默认必须——如果没有找到类型与属性类型匹配的bean则抛出异常)
// 也可以用在set方法上,ref引用,@Qualifier来byName寻找
@Autowired
public void setClazz(@Qualifier("c2") Clazz clazz) {this.clazz = clazz;
}

3.2.7 @Resource

  • 属性注解,也用于声明属性自动装配

  • 默认装配方式为byName,如果根据byName没有找到对应的bean,则继续根据byType寻找对应的bean,根据byType如果依然没有找到Bean或者找到不止一个类型匹配的bean,则抛出异常。

四,动态代理

代理设计模式的优点:将通用性的工作都交给代理对象完成,被代理对象只需专注自己的核心业务。

动态代理,几乎可以为所有的类产生代理对象

4.1 JDK动态代理类实现

JDK动态代理是通过被代理类实现的接口来创建代理对象的,因此JDK动态代理只能代理实现了接口的类的对象。没有实现接口的类是不能用这种方式产生代理对象。

//使用代理对象调用方法,并不会执行调用的方法,
//而是进入到创建代理对象时指定的InvocationHandler类种的invoke方法,调用的方法作为一个Method参数,传递给了invoke方法

/**** JDK动态代理:是通过被代理对象实现的接口产生其代理对象的* 1.创建一个类,实现InvocationHandler接口,重写invoke方法* 2.在类种定义一个Object类型的变量,并提供这个变量的有参构造器,用于将被代理对象传递进来* 3.定义getProxy方法,用于创建并返回代理对象*/
public class JDKDynamicProxy implements InvocationHandler {//被代理对象private Object obj;public JDKDynamicProxy(Object obj) {this.obj = obj;}//产生代理对象,返回代理对象public Object getProxy(){//1.获取被代理对象的类加载器ClassLoader classLoader = obj.getClass().getClassLoader();//2.获取被代理对象的类实现的接口Class<?>[] interfaces = obj.getClass().getInterfaces();//3.产生代理对象(通过被代理对象的类加载器及实现的接口)//第一个参数:被代理对象的类加载器//第二个参数:被代理对象实现的接口//第三个参数:使用产生代理对象调用方法时,用于拦截方法执行的处理器Object proxy = Proxy.newProxyInstance(classLoader, interfaces,this);return proxy;}public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {begin();Object returnValue = method.invoke(obj,args);  //执行method方法(insert)commit();return returnValue;}public void begin(){System.out.println("----------开启事务");}public void commit(){System.out.println("----------提交事务");}
}// --------------测试------------------//创建被代理对象
BookDAOImpl bookDAO = new BookDAOImpl();
StudentDAOImpl studentDAO = new StudentDAOImpl();//创建动态代理类对象,并将被代理对象传递到代理类中赋值给obj
JDKDynamicProxy jdkDynamicProxy = new JDKDynamicProxy(studentDAO);//proxy就是产生的代理对象:产生的代理对象可以强转成被代理对象实现的接口类型
GenaralDAO proxy = (GenaralDAO)jdkDynamicProxy.getProxy();//使用代理对象调用方法,并不会执行调用的方法,
//而是进入到创建代理对象时指定的InvocationHandler类种的invoke方法
//调用的方法作为一个Method参数,传递给了invoke方法
proxy.insert(student);

4.2 CGLib动态代理实现

CGLib动态代理,是通过创建被代理类的子类来创建代理对象的,因此即使没有实现任何接口的类也可以通过CGLib产生代理对象

因为是创建子类,因此CGLib动态代理不能为final类创建代理对象

添加CGLib的依赖
<!-- https://mvnrepository.com/artifact/cglib/cglib -->
<dependency><groupId>cglib</groupId><artifactId>cglib</artifactId><version>3.3.0</version>
</dependency>
/*** 1.添加cglib依赖* 2.创建一个类,实现MethodInterceptor接口,同时实现接口中的intercept方法* 3.在类中定义一个Object类型的变量,并提供这个变量的有参构造器,用于传递被代理对象* 4.定义getProxy方法创建并返回代理对象(代理对象是通过创建被代理类的子类来创建的)*/
public class CGLibDynamicProxy implements MethodInterceptor {private Object obj;public CGLibDynamicProxy(Object obj) {this.obj = obj;}public Object getProxy(){Enhancer enhancer = new Enhancer();enhancer.setSuperclass(obj.getClass());enhancer.setCallback(this);Object proxy = enhancer.create();return proxy;}public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {begin();Object returnValue = method.invoke(obj,objects); //通过反射调用被代理类的方法commit();return returnValue;}public void begin(){System.out.println("----------开启事务");}public void commit(){System.out.println("----------提交事务");}
}// ------------测试 ------------//创建被代理对象
BookDAOImpl bookDAO = new BookDAOImpl();
StudentDAOImpl studentDAO = new StudentDAOImpl();//通过cglib动态代理类创建代理对象
CGLibDynamicProxy cgLibDynamicProxy = new CGLibDynamicProxy(bookDAO);
//代理对象实际上是被代理对象子类,因此代理对象可直接强转为被代理类类型
BookDAOImpl proxy = (BookDAOImpl) cgLibDynamicProxy.getProxy();//使用对象调用方法,实际上并没有执行这个方法,而是执行了代理类中的intercept方法,将当前调用的方法以及方法中的参数传递到intercept方法
proxy.update();

五、Spring AOP

5.1 AOP的概念

aspect oriented programming 面向切面编程,是一种利用横切的技术,对原有的业务逻辑进行拦截,并且可以在这个拦截的横切面上添加特点的业务逻辑,实现不改变代码对原有业务的增强。

底层的实现就是动态代理。

连接点 joinPoint:原始程序中的方法

切入点pointCut:被spring横切的方法

通知/增强:

切点:添加到切入点的 新增的业务方法

切面:定义切点方法的类

5.2 Spring AOP 框架部署

5.2.1 创建maven项目

5.2.2 添加依赖

<dependency><groupId>org.springframework</groupId><artifactId>spring-context</artifactId><version>5.2.13.RELEASE</version>
</dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-aspects</artifactId><version>5.2.13.RELEASE</version>
</dependency>

5.3  AOP配置 --基于xml

例子:在DAO方法中添加开启事务和提交事务的逻辑

5.3.1 创建一个类,定义要添加的业务逻辑 --- 这个类就是切面,里面定义的方法就是切点

public class TxManager {public void begin(){System.out.println("-----------开启事务");}public void commit(){System.out.println("-----------提交事务");}
}

5.3.2 配置AOP

<?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:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsd"><bean id="bookDAO" class="com.qfedu.dao.BookDAOImpl"></bean><bean id="studentDAO" class="com.qfedu.dao.StudentDAOImpl"></bean><!----><bean id="txManager" class="com.qfedu.utils.TxManager"></bean><aop:config><!--声明切入点--><aop:pointcut id="book_all" expression="execution(* com.qfedu.dao.*.*(..))"/><!--声明txManager为切面类--><aop:aspect ref="txManager"><!--通知--><aop:before method="begin" pointcut-ref="book_all"/><aop:after method="commit" pointcut-ref="book_all"/></aop:aspect></aop:config></beans>

总结AOP的开发步骤:

  1. 创建一个切面类,定义切点方法
  2. 将切面类配置给spring容器
  3. 声明切入点
  4. 配置AOP的通知策略

5.4 切入点的声明

5.4.1 各种切入点声明方式

<!--使用aop:pointcut标签声明切入点:切入点可以是一个方法-->
<aop:pointcut id="book_insert" expression="execution(* com.qfedu.dao.BookDAOImpl.insert())"/><!--BookDAOImpl类中所有无参数无返回值的方法-->
<aop:pointcut id="book_pc1" expression="execution(void com.qfedu.dao.BookDAOImpl.*())"/><!--BookDAOImpl类中所有无返回值的方法-->
<aop:pointcut id="book_pc2" expression="execution(void com.qfedu.dao.BookDAOImpl.*(..))"/><!--BookDAOImpl类中所有无参数的方法-->
<aop:pointcut id="book_pc3" expression="execution(* com.qfedu.dao.BookDAOImpl.*())"/><!--BookDAOImpl类中所有方法-->
<aop:pointcut id="book_pc4" expression="execution(* com.qfedu.dao.BookDAOImpl.*(..))"/><!--dao包中所有类中的所有方法-->
<aop:pointcut id="pc5" expression="execution(* com.qfedu.dao.*.*(..))"/><!--dao包中所有类中的insert方法-->
<aop:pointcut id="pc6" expression="execution(* com.qfedu.dao.*.insert(..))"/>

5.4.2 AOP使用的注意事项

如果要使用spring aop 面向切面编程,调用切入点方法的对象必须是通过spring容器获取的。

如果一个类中的方法被声明为切入点并织入了切点之后,通过spring容器获取该类对象,实际获取到的是一个代理对象

如果一个类中的方法没有被声明为切入点,通过spring容器获取的就是这个类真实的对象。

//BookServiceImpl bookService = new BookServiceImpl();
BookServiceImpl bookService = (BookServiceImpl) context.getBean("bookServiceImpl");
bookService.addBook();

5.5 AOP的通知策略

AOP的通知策略就是声明将切面类中的切点方法 如何织入到切入点

  • before -- 前置通知
  • after -- 后置 通知
  • after-throwing -- 异常之后的通知
  • after-returning -- 方法返回值之后,与 after的时机属于一个时间点,看那个先配置就先执行那个
  • around   -- 环绕通知,定义环绕通知的切点方法要遵守特定的规则
<bean id="myAspect" class="com.qfedu.utils.MyAspect"></bean>
<aop:config><!--使用aop:pointcut标签声明切入点:切入点可以是一个方法--><aop:pointcut id="book_insert" expression="execution(* com.qfedu.dao.BookDAOImpl.insert())"/><aop:aspect ref="myAspect"><!--aop:before 前置通知,切入到指定切入点之前--><aop:before method="method1" pointcut-ref="book_insert"/><!--aop:after 后置通知,切入到指定切入点之后--><aop:after method="method2" pointcut-ref="book_insert"/><!--aop:after-throwing 异常通知,切入点抛出异常之后--><aop:after-throwing method="method3" pointcut-ref="book_insert"/><!--aop:after-returning 方法返回值返回之后,对于一个Java方法而言return返回值也是方法的一部分因此“方法返回值返回之后”和“方法执行结束”是同一个时间点,随意after 和 after-returning根据配置的顺序决定执行顺序--><aop:after-returning method="method4" pointcut-ref="book_insert"/><aop:around method="method5" pointcut-ref="book_insert"/></aop:aspect></aop:config>
public class MyAspect {public void method1(){System.out.println("~~~~~~~method1");}public void method2(){System.out.println("~~~~~~~method2");}public void method3(){System.out.println("~~~~~~~method3");}public void method4(){System.out.println("~~~~~~~method4");}//环绕通知的切点方法,必须准守如下的定义规则://1.必须带有一个ProceedingJoinPoint类型的参数//2.必须有Object类型的返回值//3.在前后增强的业务逻辑之间执行Object v = point.proceed();//4.方法最后返回vpublic Object method5(ProceedingJoinPoint point) throws Throwable {System.out.println("~~~~~~~method5---before");//此代码的执行,就表示切入点方法的执行Object v = point.proceed();System.out.println("~~~~~~~method5---after");return v;}}

相关文章:

spring 笔记

一、spring概述 1.1 spring介绍 spring是一个轻量级的控制反转和面向切面的容器框架&#xff0c;用来解决企业项目开发的复杂度问题---解耦 轻量级&#xff1a;体积小&#xff0c;对代码没有侵入性控制反转&#xff1a;IOC inverse of control&#xff0c; 把创建对象的工作交…...

Java日志框架学习

首先&#xff0c;Java日志框架可以分为两类&#xff1a;门面型日志框架和记录型日志框架。 门面型日志框架 JCL&#xff1a;Java日志接口&#xff0c;后更名为Commons LoggingSLF4J&#xff1a;是一套简易Java日志门面&#xff0c;本身并无日志的实现 记录型日志框架 JUL&a…...

基础面试题:堆和栈的区别

面试题&#xff1a;堆和栈的区别&#xff08;往往讲的是内存zha&#xff09; 为什么说访问栈栈比访问堆快些&#xff1f; 目录 一、数据结构中的堆栈 1、数据结构中的堆 1&#xff09;堆的定义 2&#xff09;堆的效率 2、 数据结构中的栈 二、内存中的堆栈 1、内存堆的定义…...

(干货教程)在VSCode并使用chatgtp插件编写CC++语言程序

&#xff08;干货教程&#xff09;在VSCode并使用chatgtp插件编写CC语言程序 下载并安装VSCODE 第1步&#xff0c;下载VSCODE https://code.visualstudio.com/Download 第2步&#xff0c;安装VSCODE 安装过程较简单&#xff0c;这里省略。 安装好后效果如图&#xff1a…...

【思维模型】概率思维的价值:找到你的人生算法,实现阶级跃迁!

把同样公平的机会放在放在很多人面前,不同的人生算法,会得到迥然不同的结果。 概率思维是什么? 【ChatGPT】概率思维是一种通过使用数学模型来思考和评估不确定性事件的方法。它通过计算不同可能性的概率来预测事件的结果,并评估风险和机会。 概率思维的价值在于它可以帮…...

SpringBoot + kotlin/java + Mybatis-Plus +Sqlite + Gradle多模块项目

前言 我自己的业务项目&#xff0c;先用kotlinspringboot 搭建&#xff0c; 发现gradle支持kts脚本&#xff0c;于是我就搭建试试。我就选用了最流行的Sqlite内嵌数据库,虽然H2也不错&#xff0c;但是Sqlite才是最流行的。orm框架我还是选择了Mybatis-Plus &#xff0c;为此中…...

Docker 容器与容器云读书笔记(一)

最近都没时间看书&#xff0c;闲暇之余看看书&#xff0c;写写笔记&#xff0c;记录一下这难得的时光。 docker容器的出现 2013年初&#xff0c; 一个名字从云计算领域横空出世&#xff0c;并在整个IT行业激起千层浪&#xff0c;这就是Docker。Docker选择容器作为核心和基础&…...

软件设计(九)

软件设计&#xff08;八&#xff09;https://blog.csdn.net/ke1ying/article/details/128954569?spm1001.2014.3001.5501 81、模块A将学生信息&#xff0c;即学生姓名、学号、手机等放到一个结构体系中&#xff0c;传递给模块B&#xff0c;模块A和B之间的耦合类型为 什么耦合…...

FoveaBox原理与代码解析

paper&#xff1a;FoveaBox: Beyond Anchor-based Object Detectorcode&#xff1a;https://github.com/taokong/FoveaBox背景基于anchor的检测模型需要仔细设计anchor&#xff0c;常用方法之一是根据特定数据集的统计结果确定anchor的number、scale、ratio等&#xff0c;但这种…...

Linux内核启动(1,0.11版本)启动BIOS与加载内核

从电源到启动BIOS 从我们按下启动电源到BIOS&#xff0c;按下电源–>主板会向电源组发出信号–> 接受到信号后&#xff0c;当主板收到电源正常启动信号后&#xff0c;主板会启动CPU(CPU重置所有寄存器数据&#xff0c;并且初始化数据)&#xff0c;比如32位系统&#xff…...

python制作贪吃蛇小游戏,畅玩无限制

前言 大家早好、午好、晚好吖 ❤ ~ 现在这年头&#xff0c;无论玩个什么游戏都有健康机制&#xff0c; 这让我们愉悦玩游戏得步伐变得承重起来&#xff0c; 于是无聊之下我写了个贪吃蛇小游戏&#xff0c;来玩个快乐 代码展示 导入模块 import random import sys import …...

MySQL-InnoDB数据页结构浅析

在MySQL-InnoDB行格式浅析中&#xff0c;们简单提了一下 页 的概念&#xff0c;它是 InnoDB 管理存储空间的基本单位&#xff0c;一个页的大小一般是 16KB 。 InnoDB 为了不同的目的而设计了许多种不同类型的 页&#xff1a; 存放表空间头部信息的页存放 Insert Buffer信息的…...

Java、JSP职工人事管理系统设计与实现

技术&#xff1a;Java、JSP等摘要&#xff1a;现在随着我们这个社会的计算机技术的快速发展&#xff0c;计算机在企业管理中得到普遍的应用&#xff0c;现在我们利用计算机在实现企业职工的管理越来越重要。当今社会是快速发展的信息社会&#xff0c;自动化信息的作用也变得越来…...

数据结构与算法这么难,为什么我们还要学习?

文章目录前言1. 数据结构与算法是什么&#xff1f;2. 为什么数据结构与算法很难&#xff1f;3. 如何系统学习数据结构与算法&#xff1f;&#x1f351; 复杂度&#x1f351; 线性表&#x1f351; 树形结构&#x1f351; 图&#x1f351; 排序&#x1f351; 字符串&#x1f351;…...

剑指 Offer 52. 两个链表的第一个公共节点

摘要 剑指 Offer 52. 两个链表的第一个公共节点 一、双指针解法 使用双指针的方法&#xff0c;可以将空间复杂度降至 O(1)。只有当链表 headA headB都不为空时&#xff0c;两个链表才可能相交。因此首先判断链表 headA和 headB是否为空&#xff0c;如果其中至少有一个链表为…...

可以写进简历的软件测试电商项目,不进来get一下?

前言 说实话&#xff0c;在找项目的过程中&#xff0c;我下载过&#xff08;甚至付费下载过&#xff09;N多个项目、联系过很多项目的作者&#xff0c;但是绝大部分项目&#xff0c;在我看来&#xff0c;并不适合你拿来练习&#xff0c;它们或多或少都存在着“问题”&#xff…...

蓝桥杯-算法-印章问题

这个题真的顶啊&#xff01;思路&#xff1a;n种图案&#xff0c;m张印章&#xff0c;每一个图案的概率是1/n&#xff0c;这个概率以后用P表示首先我们定义dp[i][j]是买了i张印章&#xff08;对应于上面的m&#xff09;&#xff0c;凑齐j种图案的概率&#xff08;对应于上面的n…...

戴尔游匣G16电脑U盘安装系统操作教程分享

戴尔游匣G16电脑U盘安装系统操作教程分享。有用户在使用戴尔游匣G16电脑的时候遇到了系统问题&#xff0c;比如电脑蓝屏、自动关机重启、驱动不兼容等问题。遇到这些问题如果无法进行彻底解决&#xff0c;我们可以通过U盘重新安装系统的方法来解决&#xff0c;因为这些问题一般…...

2023数学建模美赛赛题思路分析 2023美赛 美国大学生数学建模数模

将在本帖更新2023美国大学生数学建模数模美赛各个赛题思路&#xff0c;大家可以点赞收藏&#xff01; 一、参赛报名 组队参赛&#xff08;每队人数3人&#xff0c;专业不限&#xff09;。 二、赛题思路及资料 会在本帖更新思路分析&#xff0c;Q群可领取模型代码/赛题思路资料…...

vue3与vue2的对比

Vue 3.0 和 Vue 2.0 是 Vue 前端框架的两个主要版本&#xff0c;它们有着不同的更新和优化&#xff1a; Vue 3.0 主要更新内容&#xff1a; 采用 TypeScript 作为开发语言&#xff0c;提高了代码的类型安全性。 速度更快&#xff0c;内存使用更少&#xff0c;支持大规模数据处…...

k8s从入门到放弃之Ingress七层负载

k8s从入门到放弃之Ingress七层负载 在Kubernetes&#xff08;简称K8s&#xff09;中&#xff0c;Ingress是一个API对象&#xff0c;它允许你定义如何从集群外部访问集群内部的服务。Ingress可以提供负载均衡、SSL终结和基于名称的虚拟主机等功能。通过Ingress&#xff0c;你可…...

Linux相关概念和易错知识点(42)(TCP的连接管理、可靠性、面临复杂网络的处理)

目录 1.TCP的连接管理机制&#xff08;1&#xff09;三次握手①握手过程②对握手过程的理解 &#xff08;2&#xff09;四次挥手&#xff08;3&#xff09;握手和挥手的触发&#xff08;4&#xff09;状态切换①挥手过程中状态的切换②握手过程中状态的切换 2.TCP的可靠性&…...

转转集团旗下首家二手多品类循环仓店“超级转转”开业

6月9日&#xff0c;国内领先的循环经济企业转转集团旗下首家二手多品类循环仓店“超级转转”正式开业。 转转集团创始人兼CEO黄炜、转转循环时尚发起人朱珠、转转集团COO兼红布林CEO胡伟琨、王府井集团副总裁祝捷等出席了开业剪彩仪式。 据「TMT星球」了解&#xff0c;“超级…...

是否存在路径(FIFOBB算法)

题目描述 一个具有 n 个顶点e条边的无向图&#xff0c;该图顶点的编号依次为0到n-1且不存在顶点与自身相连的边。请使用FIFOBB算法编写程序&#xff0c;确定是否存在从顶点 source到顶点 destination的路径。 输入 第一行两个整数&#xff0c;分别表示n 和 e 的值&#xff08;1…...

3-11单元格区域边界定位(End属性)学习笔记

返回一个Range 对象&#xff0c;只读。该对象代表包含源区域的区域上端下端左端右端的最后一个单元格。等同于按键 End 向上键(End(xlUp))、End向下键(End(xlDown))、End向左键(End(xlToLeft)End向右键(End(xlToRight)) 注意&#xff1a;它移动的位置必须是相连的有内容的单元格…...

有限自动机到正规文法转换器v1.0

1 项目简介 这是一个功能强大的有限自动机&#xff08;Finite Automaton, FA&#xff09;到正规文法&#xff08;Regular Grammar&#xff09;转换器&#xff0c;它配备了一个直观且完整的图形用户界面&#xff0c;使用户能够轻松地进行操作和观察。该程序基于编译原理中的经典…...

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

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

GruntJS-前端自动化任务运行器从入门到实战

Grunt 完全指南&#xff1a;从入门到实战 一、Grunt 是什么&#xff1f; Grunt是一个基于 Node.js 的前端自动化任务运行器&#xff0c;主要用于自动化执行项目开发中重复性高的任务&#xff0c;例如文件压缩、代码编译、语法检查、单元测试、文件合并等。通过配置简洁的任务…...

iview框架主题色的应用

1.下载 less要使用3.0.0以下的版本 npm install less2.7.3 npm install less-loader4.0.52./src/config/theme.js文件 module.exports {yellow: {theme-color: #FDCE04},blue: {theme-color: #547CE7} }在sass中使用theme配置的颜色主题&#xff0c;无需引入&#xff0c;直接可…...

rknn toolkit2搭建和推理

安装Miniconda Miniconda - Anaconda Miniconda 选择一个 新的 版本 &#xff0c;不用和RKNN的python版本保持一致 使用 ./xxx.sh进行安装 下面配置一下载源 # 清华大学源&#xff08;最常用&#xff09; conda config --add channels https://mirrors.tuna.tsinghua.edu.cn…...