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

[Spring] Spring5——AOP 简介

目录

一、AOP 简介

1、什么是 AOP

二、AOP 底层原理

1、动态代理原理

2、基于接口的 JDK 动态代理 

3、基于继承的 CGLib 动态代理

三、底层原理实现—— JDK 动态代理

1、使用 Proxy 类的方法创建代理对象

2、JDK 动态代理示例

四、AOP 操作术语

1、连接点

2、切入点

3、通知(增强)

4、切面

五、基于 AspectJ 实现 AOP 操作(注解)

1、准备工作

2、基于 AspectJ 注解方式

3、其他通知

4、公共切入点提取

5、多个 Proxy 类增强同一个方法

6、完全注解开发

六、基于 AspectJ 实现 AOP 操作(配置文件方式)

1、示例


一、AOP 简介

1、什么是 AOP

(1)AOP 就是面向切面编程

利用 AOP 可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低提高程序的可重用性,同时提高了开发的效率

(2)简单来说,就是不需要修改源代码,但依然可以为原来的代码添加新功能

比如在登录功能的基础上,添加一个权限检查的模块。通过某些配置,将这个模块(或部分实现代码)添加到登录功能上。

二、AOP 底层原理

1、动态代理原理

利用Java的反射技术(Java Reflection),在运行时创建一个实现某些给定接口的新类(也称“动态代理类”)及其实例(对象)。代理的是接口(Interfaces),不是类(Class),也不是抽象类。

AOP 底层是通过动态代理实现的,而动态代理是基于反射来设计的。动态代理有两种情况

  • 有接口,则使用基于接口的 JDK 动态代理
  • 没有接口,则使用基于继承的 CGLib 动态代理 

2、基于接口的 JDK 动态代理 

创建接口实现类的代理(Proxy)对象,使用这个对象的 invoke 方法来增强接口实现类的方法(无论调用哪个方法都会增强)。

3、基于继承的 CGLib 动态代理

创建子类的代理对象,增强类的方法。

三、底层原理实现—— JDK 动态代理

1、使用 Proxy 类的方法创建代理对象

使用 newProxyInstance() 返回指定接口的代理类的实例,将该接口实例方法调用分配给指定的调用处理程序

经此步骤,在原本的方法的基础上,就会添加上增强的部分。

(1)newProxyInstance 方法的三个参数:

  • ClassLoader类加载器
  • interfaces,需要增强的方法所在的接口类,支持多个接口(数组形式);
  • InvocationHandler,调用处理器(程序);

(2)对第一个参数的理解

上文提到动态代理的原理,而这个类加载器其实就是基于这个原理,将增强部分与原部分得到的结果赋予这个新类,那么我们调用这个新类的方法就可以得到我们想要的增强效果。

(3)对第二个参数(特别是多个接口的情况)的理解

newProxyInstance 是为一个实现类的实例来添加增强部分的,因为明确了具体哪一个实现类,也就明确了具体的方法。

又因为一个实现类很可能是多个接口的实现类,那么在这种情况下,就需要把所有接口都传入。

(4)对第三个参数的理解

调用处理器,它其实是一个接口。

我们实现这个接口,比如叫做 A,将实现类的实例传递给 A,在 invoke 方法中进行具体操作。

2、JDK 动态代理示例

目的:增强 UserDao 里的方法。先编写好基本的接口和实现类,然后给实现类增加新的方法。

(1)代码

(1-1)创建接口,定义方法

package com.demo.dao;public interface UserDao {public int add(int a,int b);public String update(String id);
}

(1-2)创建接口实现类,实现方法

package com.demo.dao.impl;import com.demo.dao.UserDao;public class UserDaoImpl implements UserDao {@Overridepublic int add(int a, int b) {return a + b;}@Overridepublic String update(String id) {return id;}
}

(1-3)使用 Proxy 类创建接口代理对象

package com.demo.proxy;import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;// 创建代理对象的代码
public class JDKProxy implements InvocationHandler {// 创建的是谁的代理对象,就把谁传递过来,一般用有参构造private Object obj;public JDKProxy(Object obj) {this.obj = obj;}@Override // invoke 放在在代理对象创建后马上调用public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {// 增强之前System.out.println(method.getName() + " 增强之前");Object res = method.invoke(obj, args);// 增强之后System.out.println(method.getName() + " 增强之后");return res;}}

(1-4)测试代码

import com.demo.dao.UserDao;
import com.demo.dao.impl.UserDaoImpl;
import com.demo.proxy.JDKProxy;
import org.junit.Test;import java.lang.reflect.Proxy;public class ProxyTest {@Testpublic void test() {Class[] interfaces = {UserDao.class};UserDao userDao = new UserDaoImpl();UserDao userDaoProxy = (UserDao) Proxy.newProxyInstance(userDao.getClass().getClassLoader(), interfaces, new JDKProxy(userDao));System.out.println("res = " + userDaoProxy.add(2, 3));System.out.println("res = " + userDaoProxy.update("114514"));}
}

(2)输出结果

四、AOP 操作术语

1、连接点

可以被增强的类方法,就称为连接点。

2、切入点

实际被增强的类方法,称为切入点(通过切入点表达式确定,后面会讲)。

3、通知(增强)

实际被增强的逻辑部分(代码),就称为通知。

通知有 5 种类型:

  • 前置通知,原方法之前执行;
  • 后置通知,原方法之后执行;
  • 环绕通知,原方法之前和之后都执行;
  • 异常通知,原方法异常时执行;
  • 最终通知,类似 finally;

4、切面

切面是一个动作,是一个把通知(增强)应用到切入点的过程。(比如:把权限判断加入到登录这一过程,就是切面)

五、基于 AspectJ 实现 AOP 操作(注解)

前面所讲的 JDK 动态代理,是为了说明 AOP 是如何实现的。在实际应用中,不会使用这种方式实现 AOP 操作,而是通过 AspectJ 注解莱实现,对象的获取还是通过 IOC 来实现。

1、准备工作

(1)Spring 框架一般都是基于 AspectJ 实现 AOP 操作

  • AspectJ 不是 Spring 组成部分,而是一个独立的 AOP 框架,一般把 AspectJ 和 Spirng 框架一起使用,进行 AOP 操作。

(2)基于 AspectJ 实现 AOP 操作的两种方式

  • 基于 xml 配置文件实现;
  • 基于注解方式实现(常用);

(3)引入相关依赖(仅写出了 AOP 部分所需依赖)

<dependencies><!-- https://mvnrepository.com/artifact/org.springframework/spring-aop --><dependency><groupId>org.springframework</groupId><artifactId>spring-aop</artifactId><version>5.3.22</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-aspects</artifactId><version>5.3.22</version></dependency><dependency><groupId>net.sourceforge.cglib</groupId><artifactId>com.springsource.net.sf.cglib</artifactId><version>2.2.0</version></dependency><dependency><groupId>aopalliance</groupId><artifactId>aopalliance</artifactId><version>1.0</version></dependency><dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.6.8</version></dependency></dependencies>

(4)切入点表达式

(4-1)切入点表达式的作用

  • 知道对哪个类里面的哪个方法进行增强。

(4-2)语法结构

execution([权限修饰符][返回类型][类全路径][方法名称]([参数列表]))
  • 权限修饰符:private、public、……;
  • 返回类型:void、int、省略、……;
  • 参数列表:..(两个点表示方法中的参数);
  • *:表示任意权限修饰符、类、方法;

(4-3)例子

注意 * 后的空格是不能省略的,它代表了返回类型。

  • 对 com.demo.dao.BookDao 类里面的 add() 进行增强:
execution(* com.demo.dao.BookDao.add(..))
  • 对 com.demo.dao.BookDao 类里面的所有的方法进行增强:
execution(* com.demo.dao.BookDao.*(..))
  • 对 com.demo.dao 包里面所有类,类里面所有方法进行增强:
execution(* com.atguigu.dao.*.*(..))

2、基于 AspectJ 注解方式

(1)开启注解扫描以及生成代理对象

  • 可以使用配置类,也可以使用配置文件。两个标签的作用类似,就是寻找给定范围内的类是否包含对应标签。
<?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"xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"><!-- 注解扫描 --><context:component-scan base-package="com.demo"></context:component-scan><!-- 开启Aspect生成代理对象 --><aop:aspectj-autoproxy></aop:aspectj-autoproxy>
</beans>

(2)创建类,定义方法

package com.demo.dao.impl;import com.demo.dao.UserDao;
import org.springframework.stereotype.Component;@Component
public class UserDaoImpl implements UserDao {@Overridepublic void add() {System.out.println("add()......");}
}

(3)创建 Proxy 类(编写增强逻辑),并添加注解 @Aspect

  • 创建不同通知类型的方法,添加对应的注解(注解是 aspect 包中的注解),并使用切入点表达式确定目标方法。
package com.demo.proxy;import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;@Component
@Aspect
public class UserDaoProxy {@Before(value = "execution(* com.demo.dao.impl.UserDaoImpl.add(..))")public void before() { // 前置通知System.out.println("before()......");}
}

(4)测试代码

import com.demo.dao.UserDao;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class AspectBeanTest {@Testpublic void test() {ApplicationContext context = new ClassPathXmlApplicationContext("AspectBean.xml");UserDao userDao = context.getBean("userDaoImpl", UserDao.class);userDao.add();}
}

(5)输出结果

3、其他通知

(1)代码 

package com.demo.proxy;import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;@Component
@Aspect
public class UserDaoProxy {@Before(value = "execution(* com.demo.dao.impl.UserDaoImpl.add(..))")public void before() { // 前置通知System.out.println("前置通知......");}@After(value = "execution(* com.demo.dao.impl.UserDaoImpl.add(..))")public void after() { // finally 通知System.out.println("finally 通知......");}@AfterReturning(value = "execution(* com.demo.dao.impl.UserDaoImpl.add(..))")public void afterReturning() { // 后置通知System.out.println("后置通知......");}@AfterThrowing(value = "execution(* com.demo.dao.impl.UserDaoImpl.add(..))")public void afterThrowing() { // 异常通知System.out.println("异常通知......");}@Around(value = "execution(* com.demo.dao.impl.UserDaoImpl.add(..))")public void around(ProceedingJoinPoint proceedingJoinPoint) throws Throwable { // 环绕通知System.out.println("环绕通知之前......");proceedingJoinPoint.proceed();System.out.println("环绕通知之后......");}
}

(2)输出结果

(3)出现异常的输出结果

4、公共切入点提取

上面的示例代码中的切入点的 value 值都一样,可以将他们提取出来。

@Pointcut(value = "execution(* com.demo.dao.impl.UserDaoImpl.add(..))")
public void AddPoint() {}@Before(value = "AddPoint()")
public void before() { // 前置通知System.out.println("前置通知......");
}

5、多个 Proxy 类增强同一个方法

如果出现多个 Proxy 增强类都含有多同一个方法的增强,那么可以通过设置优先级来确定它们的执行(增强)顺序。

(1)在 Proxy 增强类上添加注解 @Order

  • @Order(整数值),其中整数值越小,该增强类的优先级越大。

(2)代码

package com.demo.proxy;import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;@Component
@Aspect
@Order(1)
public class UserDaoProxy {@Before(value = "execution(* com.demo.dao.impl.UserDaoImpl.add(..))")public void before() { // 前置通知System.out.println("前置通知......");}
}@Component
@Aspect
@Order(0)
class Person {@Before(value = "execution(* com.demo.dao.impl.UserDaoImpl.add(..))")public void before() {System.out.println("person 的前置通知");}
}

(3)输出结果

6、完全注解开发

(1)创建配置类,不需要创建 xml 配置文件

package com.demo.config;import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;@Configuration
@ComponentScan(basePackages = {"com.demo"})
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class Config {}

(2)测试代码

import com.demo.config.Config;
import com.demo.dao.UserDao;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;public class AspectBeanTest {@Testpublic void test() {ApplicationContext context = new AnnotationConfigApplicationContext(Config.class);UserDao userDao = context.getBean("userDaoImpl", UserDao.class);userDao.add();}
}

(3)输出结果

 

六、基于 AspectJ 实现 AOP 操作(配置文件方式)

Proxy类和目标增强类的对象的创建就是 IOC 里讲的操作,重点在于 AOP 部分的配置。

1、示例

(1)代码

(1-1)Book 类和 BookProxy 类

package com.demo.pojo;public class Book {public void buy() {System.out.println("but()......");}
}
package com.demo.proxy;public class BookProxy {public void before() {System.out.println("before 前置通知");}
}

(1-2)配置文件

<?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"xmlns:aop="http://www.springframework.org/schema/aop"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"><!-- 创建 bean 对象 --><bean id="book" class="com.demo.pojo.Book"></bean><bean id="bookProxy" class="com.demo.proxy.BookProxy"></bean><!-- 配置 AOP 增强 --><aop:config><!-- 配置切入点 --><aop:pointcut id="pc" expression="execution(* com.demo.pojo.Book.buy(..))"/><!-- 配置切面 --><aop:aspect ref="bookProxy"><!-- 配置增强作用的具体方法 --><aop:before method="before" pointcut-ref="pc"></aop:before> <!-- 表示把 before() 作用到 pc 指向的方法上 --></aop:aspect></aop:config>
</beans>

(1-3)测试代码

import com.demo.pojo.Book;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;public class XmlTest {@Testpublic void test() {ApplicationContext context = new ClassPathXmlApplicationContext("Bean01.xml");Book book = context.getBean("book", Book.class);book.buy();}
}

(2)输出结果

相关文章:

[Spring] Spring5——AOP 简介

目录 一、AOP 简介 1、什么是 AOP 二、AOP 底层原理 1、动态代理原理 2、基于接口的 JDK 动态代理 3、基于继承的 CGLib 动态代理 三、底层原理实现—— JDK 动态代理 1、使用 Proxy 类的方法创建代理对象 2、JDK 动态代理示例 四、AOP 操作术语 1、连接点 2、切入…...

C/C++ 动态规划面试算法题

1.买卖股票的最佳时机 https://blog.csdn.net/qq_41277628/article/details/113322136 输入&#xff1a;[7,1,5,3,6,4] 输出&#xff1a;5 解释&#xff1a;在第 2 天&#xff08;股票价格 1&#xff09;的时候买入&#xff0c;在第 5 天&#xff08;股票价格 6&#xff…...

kafka伪集群部署,使用zookeeper模式

1:拉去管理kafka界面UI镜像 docker pull provectuslabs/kafka-ui2:拉去管理kafka镜像 docker pull bitnami/kafka3:docker-compose.yml version: 3.8 services:zookeeper-1:container_name: zookeeper1image: bitnami/zookeeperports:- "2181:2181"environment:- …...

Postgresql 主从复制+主从切换(流复制)

pgsql有多种主从复制方式&#xff0c;推荐的是流复制 一、前置条件 1.至少两个pgsql数据库&#xff08;可以是一台设备上的两个&#xff09; 可以参考下面的教程 pgsql编译安装&#xff1a;pgsql 编译安装&#xff08;linux&#xff09; pgsql单机多开&#xff1a;pgsql 单机…...

java获取字符串集合中每个字符并且组成一个新的集合实现

直接怼代码&#xff0c;刚好碰到了这种需求&#xff0c;也是想了可久&#xff0c;其实想想也还是挺简单的 public static void main(String[] args) { // 原始字符串集合 List<String> originalList new ArrayList<>(); originalList.add("Hello"); …...

结构型设计模式——外观模式

摘要 本文主要分析设计模式 - 结构型 - 外观(Facade)&#xff0c;它提供了一个统一的接口&#xff0c;用来访问子系统中的一群接口&#xff0c;从而让子系统更容易使用。 一、外观模式的意图 提供了一个统一的接口&#xff0c;用来访问子系统中的一群接口&#xff0c;从而让…...

【算法学习】-【双指针】-【快乐数】

LeetCode原题链接&#xff1a;202. 快乐数 下面是题目描述&#xff1a; 「快乐数」 定义为&#xff1a; 对于一个正整数&#xff0c;每一次将该数替换为它每个位置上的数字的平方和。 然后重复这个过程直到这个数变为 1&#xff0c;也可能是 无限循环 但始终变不到 1。 如果…...

【Java-LangChain:使用 ChatGPT API 搭建系统-6】处理输入-链式 Prompt Chaining Prompts

第六章&#xff0c;处理输入-链式 Prompt Chaining Prompts 在本章中&#xff0c;我们将学习如何通过将复杂任务拆分为一系列简单的子任务来链接多个 Prompt。 您可能会想&#xff0c;为什么要将任务拆分为多个 Prompt&#xff0c;而不是像我们在上一个视频中学习的那样&…...

从零手搓一个【消息队列】创建核心类, 数据库设计与实现

文章目录 一、创建核心类1, 交换机2, 交换机类型3, 队列4, 绑定5, 交换机转发 & 绑定规则6, 消息7, 消息属性 二、数据库设计1, 使用 SQLite2, 使用 MyBatis2.1, 创建 Interface2.2, 创建 xml 文件 三、硬盘管理 -- 数据库1, 创建 DataBaseManager 类2, init() 初始化数据库…...

14:00面试,14:06就出来了,这问的过于变态了。。。

前言 刚从小厂出来&#xff0c;没想到在另一家公司我又寄了。 在这家公司上班&#xff0c;每天都要加班&#xff0c;但看在钱给的比较多的份上&#xff0c;也就不太计较了。但万万没想到5月一纸通知&#xff0c;所有人不准加班了&#xff0c;不仅加班费没有了&#xff0c;薪资…...

url请求头信息

Accept Accept&#xff1a;请求报头域&#xff0c;用于指定客户端可接受哪些类型的信息。 Accept-Language Accept-Language&#xff1a;指定客户端可接受的语言类型。 Accept-Encoding Accept-Encoding&#xff1a;指定客户端可接受的内容编码。 Host Host&#xff1a;…...

【Oracle】Oracle系列之十六--数据库备份

文章目录 往期回顾1. 数据库备份的分类1.1 逻辑备份与物理备份&#xff08;1&#xff09;逻辑备份&#xff08;2&#xff09;物理备份&#xff08;3&#xff09;归档模式与非归档模式 1.2 完全备份/差异备份/增量备份 2. Oracle 逻辑备份2.1 EXP/IMP&#xff08;1&#xff09;E…...

uni-app:实现页面效果3

效果 代码 <template><view><!-- 风速风向检测器--><view class"content_position"><view class"content"><view class"SN"><view class"SN_title">设备1</view><view class&quo…...

计算机网络基础(一):网络系统概述、OSI七层模型、TCP/IP协议及数据传输

通信&#xff0c;在古代是通过书信与他人互通信息的意思。 今天&#xff0c;“通信”这个词的外沿已经得到了极大扩展&#xff0c;它目前的大意是指双方或多方借助某种媒介实现信息互通的行为。 如果按照当代汉语的方式理解“通信”&#xff0c;那么古代的互遣使节、飞鸽传书…...

互联网金融理财知识点简单总结

互联网金融理财知识点总结 互联网金融理财是指通过互联网平台进行资产管理和投资的一种金融方式。它结合了金融、科技和互联网&#xff0c;为投资者提供了更多选择和便捷性。本文将介绍互联网金融理财的关键知识点&#xff0c;包括理财基础、投资产品、风险管理和未来趋势等方…...

微信小程序template界面模板导入

我们有些时候 会有一些比较大但并不复杂的界面结构 这个时候 你可以试试这种导入模板的形式 我们在根目录创建一个 template 目录 然后下面创建一个 text文件夹下面创建一个 test.wxml 参考代码如下 <template name"textIndex"><text class "testw&…...

C/C++跨平台构建工具CMake-----在C++源码中读取CMakeLists.txt配置文件中的内容

文章目录 1.需求描述2.需求准备2.1 创建项目2.2 编辑CMakeLists.txt文件2.3 编写C文件2.4 编译构建项目 3.需求实现3.1 在CMakeLists.txt中输出日志信息3.2 增加配置生成C头文件3.3在C 源码中访问配置的值3.4 C文件中读取CMakeLists.txt中的字符串 总结 1.需求描述 当我们开发…...

【MVP争夺战】python实现-附ChatGPT解析

1.题目 MVP争夺战 知识点 :DFS搜索 时间限制:1s 空间限制:256MB 限定语言:不限 题目描述: 在星球争霸篮球赛对抗赛中,强大的宇宙战队,希望每个人都能拿到MVP。 MVP的条件是,单场最高分得分获得者,可以并列,所以宇宙战队决定在比赛中尽可能让更多的队员上场,且让所有有得…...

6 个最佳免费 Android 数据恢复软件

如果您是 Android 用户&#xff0c;您可能会发现没有回收站。然而&#xff0c;聪明的开发人员已经创建了各种 Android 数据恢复软件程序&#xff0c;可以解决各种与数据丢失相关的问题。 Android 数据恢复软件如何工作&#xff1f; 问题是当你删除一个文件时&#xff0c;它的数…...

数学建模Matlab之数据预处理方法

本文综合代码来自文章http://t.csdnimg.cn/P5zOD 异常值与缺失值处理 %% 数据修复 % 判断缺失值和异常值并修复&#xff0c;顺便光滑噪音&#xff0c;渡边笔记 clc,clear;close all; x 0:0.06:10; y sin(x)0.2*rand(size(x)); y(22:34) NaN; % 模拟缺失值 y(89:95) 50;% 模…...

如何保证Redis的HA高可用

目录 1.关于Redis2.Redis 的使用场景3.Redis的高可用3.1 哨兵模式&#xff08;Sentinel&#xff09;3.2 集群模式&#xff08;Cluster&#xff09; 4.参考 本文主要介绍Redis如何保证高可用。 1.关于Redis Redis&#xff08;Remote Dictionary Server&#xff09;是一个开源的…...

第一百六十三回 如何在任意位置显示PopupMenu

文章目录 概念介绍使用方法示例代码 我们在上一章回中介绍了PopupMenuButton相关的内容&#xff0c;本章回中将介绍如何在任意位置显示PopupMenu.闲话休提&#xff0c;让我们一起Talk Flutter吧。 概念介绍 我们在上一章回中介绍了PopupMenuButton相关的内容&#xff0c;它主…...

采用python中的opencv2的库来运用机器视觉移动物体

一. 此次我们来利用opencv2来进行机器视觉的学习 1. 首先我们先来进行一个小的案例的实现. 这次我们是将会进行一个小的矩形手势的移动. import cv2 from cvzone.HandTrackingModule import HandDetectorcap cv2.VideoCapture(0) # cap.set(3, 1280) # cap.set(4, 720) col…...

一、thymeleaf简介

1.1 什么是thymeleaf Thymeleaf是一个适用于web和独立环境的现代服务器端Java模板引擎&#xff0c;能够处理HTML、XML、JavaScript、CSS甚至纯文本。主要目标是提供一种优雅且高度可维护的创建模板的方法。 何为模板引擎呢&#xff1f;模板引擎就是为了使用户页面和业务数据…...

二分查找模版

对于一个递增序列我们要找大于等于target的数&#xff0c;返回结果的下标时 比如 序列 5 7 7 8 8 10 初始化左右指针l0 rn-1 猜测区间 [l,r] 闭区间&#xff0c;mid(lr)/2 防溢出就写成 midl(r-l)/2 如果有nums[mid]<target 那么[l,mid]这个区间的数就都小于target 更新 lmi…...

idea清空缓存类

解决办法 网上有很多是让你去清空什么maven依赖&#xff0c;但假如这个项目是你不可以大刀阔斧的话 可以清空idea缓存 选择 Invalidate 开头的 然后全选 运行重启idea OK...

PAT(Basic Level) Practice(中文) 1015德才论

前言 ※ PTA是 程序设计类实验辅助教学平台 &#xff0c;里边包含一些编程题目集以供练习。 这道题用java解&#xff0c;我试了三种解法&#xff0c;不断优化&#xff0c;但始终是三个测试点通过、三个测试点超时。我把我的代码放在这里&#xff0c;做个参考吧。 1015 德才…...

接口自动化测试的概述及流程梳理~

接下来开始学习接口自动化测试。 因为之前从来没接触过&#xff0c;所以先了解一些基础知识。 1.接口测试的概述 2.接口自动化测试流程。 接口测试概述 接口&#xff0c;又叫API&#xff08;Application Programming Interface&#xff0c;应用程序编程接口&#xff09;&a…...

竞赛 机器视觉 opencv 深度学习 驾驶人脸疲劳检测系统 -python

文章目录 0 前言1 课题背景2 Dlib人脸识别2.1 简介2.2 Dlib优点2.3 相关代码2.4 人脸数据库2.5 人脸录入加识别效果 3 疲劳检测算法3.1 眼睛检测算法3.2 打哈欠检测算法3.3 点头检测算法 4 PyQt54.1 简介4.2相关界面代码 5 最后 0 前言 &#x1f525; 优质竞赛项目系列&#x…...

虚拟货币(也称为加密货币或数字货币)的运作

虚拟币发展史 虚拟币的发展史可以追溯到20世纪末和21世纪初&#xff0c;以下是虚拟币的重要发展节点&#xff1a; 1998年&#xff1a;比特币白皮书的发布 比特币的概念最早由中本聪&#xff08;Satoshi Nakamoto&#xff09;在1998年提出&#xff0c;随后在2008年发布了一份名…...

哈尔滨做网站的oeminc/seo优化公司排名

据市场研究公司DellOro Group最新报道指出&#xff0c;数据中心和企业园区向更高速度以太网的过渡将带动未来五年以太网交换机的销售。 该调研公司表示&#xff0c;数据中心大部分支出都用于25 Gbps交换机&#xff0c;而企业园区升级则要使用大量2.5/5.0 Gbps交换机。 DellOro …...

只做彩票网站犯法吗/怎么样在百度上免费推广

说明: JavaScript的对象&#xff08;Object&#xff09;&#xff0c;本质上是键值对的集合&#xff08;Hash结构&#xff09;&#xff0c;但是传统上只能用字符串当作键。这给它的使用带来了很大的限制。 为了解决这个问题&#xff0c;ES6提供了Map数据结构。它类似于对象&…...

文库网站开发建设/企业网站营销的优缺点及案例

2019独角兽企业重金招聘Python工程师标准>>> Actor模型的本质已经被强调了无数遍&#xff1a;万物皆Actor。Actor之间只有发送消息这一种通信方式&#xff0c;例如&#xff0c;无论是管理员让工作者干活&#xff0c;还是工作者把成果交还给管理员&#xff0c;它们之…...

论述政府门户网站建设的基本意义/国外免费舆情网站有哪些软件

作用&#xff1a;不借助<router-link>实现路由跳转&#xff0c;让路由跳转更加灵活 具体编码&#xff1a; $router.push 想要导航到不同的 URL&#xff0c;则使用 router.push 方法。这个方法会向 history 栈添加一个新的记录&#xff0c;所以&#xff0c;当用户点击浏…...

培训销售网站建设/免费b2b推广网站

一.先以非授权的模式启动MongoDB非授权&#xff1a; linux/Mac : mongod -f /mongodb/etc/mongo.conf windows : mongod --config c:\mongodb\etc\mongo.conf 或者 net start mongodb &#xff08;前提是mongo安装到了服务里面&#xff09; 备注&#xff1a; /mongodb/etc/mong…...

做网站 侵权/app推广方案范例

MaxCompute2.0(原Odps)&#xff1a;通过性能评测&#xff0c;MaxCompute2.0离线计算比同类产品Hive2.0 on Tez性能优势快约90%以上&#xff1b;MaxCompute2.0从新一代执行引擎到编译引擎、基于代价的优化器全流程针对性能提升做出了卓越改进。本次评测侧重于已发布的MaxCompute…...