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

Springboot如何使用面向切面编程AOP?

Springboot如何使用面向切面编程AOP?

在 Spring Boot 中使用面向切面编程(AOP)非常简单,Spring Boot 提供了对 AOP 的自动配置支持。以下是详细的步骤和示例,帮助你快速上手 Spring Boot 中的 AOP。


1. 添加依赖

首先,在 pom.xml(Maven)或 build.gradle.kts(Gradle)中添加 Spring Boot Starter AOP 依赖:

Maven
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId>
</dependency>
Gradle-Kotlin build.gradle.kts
dependencies {implementation("org.springframework.boot:spring-boot-starter-aop")
}
implementation("org.springframework.boot:spring-boot-starter-aop")
Gradle-Groovy build.gradle
dependencies {implementation 'org.springframework.boot:spring-boot-starter-aop'
}
implementation 'org.springframework.boot:spring-boot-starter-aop'

2. 编写切面类

切面类是一个普通的 Spring Bean,使用 @Aspect 注解标记。切面类中定义了切点(Pointcut)和通知(Advice)。

示例:记录方法执行日志的切面
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;@Aspect // 标记为切面类
@Component // 标记为 Spring Bean
public class LoggingAspect {// 定义切点:拦截 com.example.service 包下的所有方法@Pointcut("execution(* com.example.service.*.*(..))")public void serviceMethods() {}// 前置通知:在目标方法执行前执行@Before("serviceMethods()")public void logBeforeMethod() {System.out.println("方法即将执行...");}
}

3. 定义目标服务类

编写一个普通的 Spring 服务类,作为 AOP 的目标对象。

示例:用户服务类
import org.springframework.stereotype.Service;@Service
public class UserService {public void createUser(String name) {System.out.println("创建用户: " + name);}public void deleteUser(String name) {System.out.println("删除用户: " + name);}
}

4. 启用 AOP 支持

Spring Boot 默认会自动启用 AOP 支持,无需额外配置。如果需要手动启用,可以在主应用类上添加 @EnableAspectJAutoProxy 注解:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.EnableAspectJAutoProxy;@SpringBootApplication
@EnableAspectJAutoProxy // 启用 AOP 支持
public class MyApplication {public static void main(String[] args) {SpringApplication.run(MyApplication.class, args);}
}

5. 运行并验证

启动 Spring Boot 应用,调用 UserService 的方法,观察切面是否生效。

示例:调用服务方法
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.stereotype.Component;@Component
public class AppRunner implements CommandLineRunner {@Autowiredprivate UserService userService;@Overridepublic void run(String... args) throws Exception {userService.createUser("Alice");userService.deleteUser("Bob");}
}
输出结果
方法即将执行...
创建用户: Alice
方法即将执行...
删除用户: Bob

6. 常用 AOP 注解

Spring AOP 提供了多种通知类型,以下是常用的注解:

注解说明
@Before在目标方法执行前执行。
@After在目标方法执行后执行(无论是否抛出异常)。
@AfterReturning在目标方法成功返回后执行。
@AfterThrowing在目标方法抛出异常后执行。
@Around环绕通知,可以控制目标方法的执行(如修改参数、返回值或捕获异常)。
示例:环绕通知
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;@Aspect
@Component
public class TimingAspect {@Around("execution(* com.example.service.*.*(..))")public Object measureExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable {long startTime = System.currentTimeMillis();Object result = joinPoint.proceed(); // 执行目标方法long endTime = System.currentTimeMillis();System.out.println("方法执行时间: " + (endTime - startTime) + "ms");return result;}
}

7. 切点表达式

切点表达式用于定义拦截的目标方法。以下是常见的表达式示例:

表达式说明
execution(* com.example.service.*.*(..))拦截 com.example.service 包下的所有方法。
execution(* com.example.service.UserService.*(..))拦截 UserService 类中的所有方法。
execution(* com.example.service.*.create*(..))拦截 com.example.service 包下以 create 开头的方法。
@annotation(com.example.LogExecutionTime)拦截带有 @LogExecutionTime 注解的方法。
自定义注解示例
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface LogExecutionTime {}

在方法上使用注解:

@Service
public class UserService {@LogExecutionTimepublic void createUser(String name) {System.out.println("创建用户: " + name);}
}

在切面中拦截注解:

@Aspect
@Component
public class LogExecutionTimeAspect {@Around("@annotation(com.example.LogExecutionTime)")public Object logExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable {long startTime = System.currentTimeMillis();Object result = joinPoint.proceed();long endTime = System.currentTimeMillis();System.out.println("方法执行时间: " + (endTime - startTime) + "ms");return result;}
}

8. 总结

  • Spring Boot 通过 spring-boot-starter-aop 提供了对 AOP 的自动支持。
  • 使用 @Aspect 定义切面类,结合 @Before@After@Around 等注解实现通知。
  • 切点表达式(execution)用于定义拦截的目标方法。
  • 可以通过自定义注解实现更灵活的切面逻辑。

通过以上步骤,你可以在 Spring Boot 中轻松实现面向切面编程(AOP),增强代码的可维护性和可扩展性。








在Spring Boot中使用面向切面编程(AOP)通常涉及以下几个步骤:

1. 引入依赖

虽然Spring Boot的spring-boot-starter已经包含了AOP的依赖,但为了确保AOP功能被正确启用,你可以在pom.xml中显式添加spring-boot-starter-aop依赖(尽管这通常是可选的,因为spring-boot-starter-web等常用starter已经包含了它)。

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId>
</dependency>

2. 启用AOP

在Spring Boot中,你通常不需要显式启用AOP,因为@SpringBootApplication注解已经包含了@EnableAspectJAutoProxy,后者负责启用AOP代理。但是,如果你想要自定义AOP代理的行为(例如,使用CGLIB而不是JDK动态代理),你可以通过添加@EnableAspectJAutoProxy注解并设置其属性来实现。

@SpringBootApplication
@EnableAspectJAutoProxy(proxyTargetClass = true) // 使用CGLIB代理
public class MySpringBootApplication {public static void main(String[] args) {SpringApplication.run(MySpringBootApplication.class, args);}
}

然而,在大多数情况下,默认设置就足够了。

3. 定义切面类

切面类是一个用@Aspect注解标记的类,它包含了切点(pointcut)和通知(advice)。

  • 切点:定义了哪些方法将被拦截。
  • 通知:定义了拦截到方法时要执行的操作。
@Aspect
@Component
public class MyAspect {// 定义一个切点,匹配所有com.example.service包下的所有方法@Pointcut("execution(* com.example.service..*(..))")public void myPointcut() {// 这是一个空方法,仅用于定义切点表达式}// 在方法执行之前执行@Before("myPointcut()")public void beforeAdvice(JoinPoint joinPoint) {System.out.println("Before method: " + joinPoint.getSignature());}// 在方法执行之后执行(无论是否抛出异常)@After("myPointcut()")public void afterAdvice(JoinPoint joinPoint) {System.out.println("After method: " + joinPoint.getSignature());}// 在方法执行之后执行(仅当方法正常返回时)@AfterReturning(pointcut = "myPointcut()", returning = "result")public void afterReturningAdvice(JoinPoint joinPoint, Object result) {System.out.println("After returning method: " + joinPoint.getSignature() + " with result: " + result);}// 在方法抛出异常时执行@AfterThrowing(pointcut = "myPointcut()", throwing = "exception")public void afterThrowingAdvice(JoinPoint joinPoint, Throwable exception) {System.out.println("After throwing method: " + joinPoint.getSignature() + " with exception: " + exception);}// 环绕通知,可以在方法执行前后自定义逻辑@Around("myPointcut()")public Object aroundAdvice(ProceedingJoinPoint joinPoint) throws Throwable {System.out.println("Before proceeding method: " + joinPoint.getSignature());Object result = joinPoint.proceed(); // 执行目标方法System.out.println("After proceeding method: " + joinPoint.getSignature() + " with result: " + result);return result;}
}

4. 应用切面

一旦你定义了切面类并将其作为Spring组件(通过@Component注解)注册到Spring容器中,Spring AOP将自动应用这些切面到匹配的bean上。

注意事项

  • 切面类本身必须是一个Spring管理的bean,因此通常会在切面类上使用@Component或其他相关的Spring注解。
  • 切点表达式定义了哪些方法将被拦截。你可以使用AspectJ的切点表达式语言(Pointcut Expression Language, PEL)来编写复杂的切点表达式。
  • 通知方法可以有参数,这些参数可以是JoinPointProceedingJoinPoint(对于环绕通知)或任何由切点表达式捕获的参数(通过@Args注解)。
  • 环绕通知必须处理目标方法的调用(通过ProceedingJoinPoint.proceed()),并且可以返回结果或抛出异常。

通过以上步骤,你就可以在Spring Boot项目中成功使用AOP来实现横切关注点(如日志记录、事务管理、权限校验等)的分离。








在 Spring Boot 中使用面向切面编程(AOP)可以帮助你分离横切关注点,如日志记录、事务管理等,从主要业务逻辑中分离出来。Spring AOP 是基于代理的实现,默认情况下支持方法级别的拦截。下面是如何在 Spring Boot 应用中配置和使用 AOP 的步骤:

1. 添加依赖

首先,确保你的 build.gradlepom.xml 文件中包含了 spring-boot-starter-aop 依赖。

对于 Gradle,添加如下依赖到你的 build.gradle 文件:

dependencies {implementation 'org.springframework.boot:spring-boot-starter-aop'
}

对于 Maven,在你的 pom.xml 文件中添加:

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId>
</dependency>

2. 启用 AOP 支持

Spring Boot 自动配置了 AOP 支持,所以通常不需要额外的手动配置。但是,如果你的应用有多个配置类,确保它们被正确扫描到。一般情况下,只需保证主应用程序类或配置类上包含 @EnableAspectJAutoProxy 注解(尽管大多数情况下自动配置已经足够)。

import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;@Configuration
@EnableAspectJAutoProxy
public class AopConfig {
}

不过,如果你只是简单地使用 Spring Boot,并且没有特别复杂的配置需求,这个注解通常是不必要的,因为 Spring Boot 已经为你自动启用了 AOP 支持。

3. 创建一个切面

创建一个类并使用 @Aspect 注解标记它。然后,定义切入点(Pointcut)和通知(Advice),例如前置通知(@Before)、后置通知(@After)、返回通知(@AfterReturning)、异常通知(@AfterThrowing)和环绕通知(@Around)。

示例代码:

import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;@Aspect
@Component
public class LoggingAspect {@Before("execution(* com.example.demo.service.*.*(..))")public void beforeMethodExecution() {System.out.println("A method in the service layer is about to be called.");}
}

4. 定义切入点表达式

上述例子中的 "execution(* com.example.demo.service.*.*(..))" 是一个切入点表达式,表示匹配 com.example.demo.service 包下的所有类的所有方法。你可以根据需要调整此表达式来精确控制哪些方法会被拦截。

5. 测试你的切面

最后,编写一些测试用例或者运行你的应用来验证 AOP 切面是否按预期工作。确保目标方法被调用时,相应的通知也会被执行。

通过以上步骤,你应该能够在 Spring Boot 应用中成功配置并使用 AOP。这种方式不仅能够帮助你清晰地分离关注点,还能使代码更加简洁和易于维护。








在 Spring Boot 中使用面向切面编程(AOP)可以高效地实现日志记录、事务管理、权限校验等横切关注点。以下是 详细步骤和实际应用场景 的总结:


1. 添加依赖

Spring Boot 默认通过 spring-boot-starter-aop 提供对 AOP 的自动配置支持:

Maven
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-aop</artifactId>
</dependency>
Gradle
dependencies {implementation("org.springframework.boot:spring-boot-starter-aop")
}

2. 编写切面类

切面类需用 @Aspect@Component 注解标记,定义切点和通知。

示例:日志记录切面
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;@Aspect
@Component
public class LoggingAspect {// 定义切点:拦截 service 包下的所有方法@Pointcut("execution(* com.example.service.*.*(..))")public void serviceMethods() {}// 前置通知:方法执行前记录日志@Before("serviceMethods()")public void logMethodStart() {System.out.println("方法开始执行...");}// 后置通知:方法执行后记录日志(无论是否异常)@After("serviceMethods()")public void logMethodEnd() {System.out.println("方法执行结束。");}// 环绕通知:计算方法执行时间@Around("serviceMethods()")public Object measureTime(ProceedingJoinPoint joinPoint) throws Throwable {long start = System.currentTimeMillis();Object result = joinPoint.proceed(); // 执行目标方法long end = System.currentTimeMillis();System.out.println("方法执行耗时: " + (end - start) + "ms");return result;}
}

3. 定义目标服务

编写一个普通的 Spring Bean 作为切面拦截的目标。

示例:用户服务
@Service
public class UserService {public void createUser(String name) {System.out.println("创建用户: " + name);}
}

4. 验证效果

调用 UserService 的方法时,切面逻辑自动生效:

@SpringBootApplication
public class Application {public static void main(String[] args) {ConfigurableApplicationContext context = SpringApplication.run(Application.class, args);UserService userService = context.getBean(UserService.class);userService.createUser("Alice");}
}
输出结果
方法开始执行...
创建用户: Alice
方法执行结束。
方法执行耗时: 2ms

5. 核心注解详解

(1) 切点表达式(Pointcut)
  • 语法execution(修饰符 返回类型 包名.类名.方法名(参数类型))
  • 常用示例
    • execution(* com.example.service.*.*(..)):拦截 service 包下所有类的所有方法。
    • execution(* com.example.service.UserService.create*(..)):拦截 UserService 中以 create 开头的方法。
    • @annotation(com.example.LogTrack):拦截带有 @LogTrack 注解的方法。
(2) 通知类型(Advice)
注解说明
@Before目标方法执行前触发。
@After目标方法执行后触发(无论是否抛出异常)。
@AfterReturning目标方法成功返回后触发(可获取返回值)。
@AfterThrowing目标方法抛出异常后触发(可捕获异常对象)。
@Around包裹目标方法,可控制方法执行、修改参数或返回值。
示例:获取方法参数和返回值
@Aspect
@Component
public class DataAspect {@AfterReturning(pointcut = "execution(* com.example.service.*.*(..))",returning = "result")public void logResult(Object result) {System.out.println("方法返回值: " + result);}@Before("execution(* com.example.service.*.*(..)) && args(name)")public void logArgument(String name) {System.out.println("方法参数: " + name);}
}

6. 高级用法

(1) 自定义注解实现切面

定义注解标记需要拦截的方法,提高代码可读性。

步骤1:定义注解
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface LogTrack {}
步骤2:在方法上使用注解
@Service
public class OrderService {@LogTrackpublic void placeOrder(String orderId) {System.out.println("下单成功: " + orderId);}
}
步骤3:切面拦截注解
@Aspect
@Component
public class LogTrackAspect {@Around("@annotation(com.example.LogTrack)")public Object trackMethod(ProceedingJoinPoint joinPoint) throws Throwable {System.out.println("开始追踪方法...");Object result = joinPoint.proceed();System.out.println("追踪结束。");return result;}
}

(2) 处理异常

@AfterThrowing 中捕获并处理异常。

@Aspect
@Component
public class ExceptionAspect {@AfterThrowing(pointcut = "execution(* com.example.service.*.*(..))",throwing = "ex")public void handleException(Exception ex) {System.out.println("捕获异常: " + ex.getMessage());// 发送报警邮件或记录日志}
}

7. 常见问题与解决

问题1:切面未生效
  • 原因
    • 切面类未被 Spring 管理(缺少 @Component)。
    • 切点表达式未匹配到目标方法。
    • 目标方法未被 Spring 代理(如直接通过 new 创建对象)。
  • 解决
    • 确保切面类添加了 @Component
    • 使用 @Autowired 获取 Bean,而非直接实例化。
问题2:环绕通知未调用 proceed()
  • 现象:目标方法未执行。
  • 解决:在 @Around 方法中必须调用 joinPoint.proceed()

8. 实际应用场景

  1. 日志记录:自动记录方法入参、返回值、执行时间。
  2. 事务管理:结合 @Transactional 实现声明式事务。
  3. 权限校验:在方法执行前检查用户权限。
  4. 性能监控:统计接口耗时,优化慢查询。
  5. 缓存管理:在方法执行前后操作缓存(如 Redis)。

总结

Spring Boot 通过简化配置和自动代理机制,使得 AOP 的实现非常便捷。核心步骤:

  1. 添加 spring-boot-starter-aop 依赖。
  2. 使用 @Aspect@Component 定义切面类。
  3. 通过切点表达式精准定位目标方法。
  4. 选择合适的通知类型(@Before@Around 等)实现横切逻辑。

掌握 AOP 后,可以大幅减少重复代码,提升系统的可维护性和扩展性。








相关文章:

Springboot如何使用面向切面编程AOP?

Springboot如何使用面向切面编程AOP? 在 Spring Boot 中使用面向切面编程&#xff08;AOP&#xff09;非常简单&#xff0c;Spring Boot 提供了对 AOP 的自动配置支持。以下是详细的步骤和示例&#xff0c;帮助你快速上手 Spring Boot 中的 AOP。 1. 添加依赖 首先&#xff…...

ThreadLocal源码解析

文章目录 一、概述二、get()方法三、set()方法四、可能导致的内存泄漏问题五、remove六、思考&#xff1a;为什么要将ThreadLocalMap的value设置为强引用&#xff1f; 一、概述 ThreadLocal是线程私有的&#xff0c;独立初始化的变量副本。存放在和线程进行绑定的ThreadLocalMa…...

Maven的单元测试

1. 单元测试的基本概念 单元测试&#xff08;Unit Testing&#xff09; 是一种软件测试方法&#xff0c;专注于测试程序中的最小可测试单元——通常是单个类或方法。通过单元测试&#xff0c;可以确保每个模块按预期工作&#xff0c;从而提高代码的质量和可靠性。 2.安装和配…...

深度学习 Pytorch 深层神经网络

在之前已经学习了三种单层神经网络&#xff0c;分别为实现线性方程的回归网络&#xff0c;实现二分类的逻辑回归&#xff08;二分类网络&#xff09;&#xff0c;以及实现多分类的softmax回归&#xff08;多分类网络&#xff09;。从本节开始&#xff0c;我们将从单层神经网络展…...

【python】三帧差法实现运动目标检测

三帧差法是一种常用的运动目标检测方法&#xff0c;它通过比较连续三帧图像之间的差异来检测运动物体。这种方法尤其适用于背景变化较小的场景。 目录 1 方案 2 实践 ① 代码 ② 效果图 1 方案 具体步骤如下&#xff1a; ① 读取视频流&#xff1a;使用cv2.VideoCapture()…...

机器人抓取与操作经典规划算法(深蓝)——2

1 经典规划算法 位姿估计&#xff1a;&#xff08;1&#xff09;相机系位姿 &#xff08;2&#xff09;机器人系位姿 抓取位姿&#xff1a;&#xff08;1&#xff09;抓取位姿计算 &#xff08;2&#xff09;抓取评估和优化 路径规划&#xff1a;&#xff08;1&#xff09;笛卡…...

WGCLOUD服务器资源监控软件使用笔记 - Token is error是什么错误

[wgcloud-agent]2025/01/30 10:41:30 WgcloudAgent.go:90: 主机监控信息上报server开始 [wgcloud-agent]2025/01/30 10:41:30 WgcloudAgent.go:99: 主机监控信息上报server返回信息: {"result":"Token is error"} 这个错误是因为agent配置的wgToken和serv…...

在排序数组中查找元素的第一个和最后一个位置(力扣)

一.题目介绍 二.题目解析 使用二分进行查找 2.1处理边界情况 如果数组为空&#xff0c;直接返回 [-1, -1]&#xff0c;因为无法找到目标值。 int[] ret new int[2]; ret[0] ret[1] -1; if (nums.length 0) return ret; 2.2查找左端点&#xff08;目标值开始位置&#…...

Kafka的消息协议

引言 在学习MQTT消息协议的时候我常常思考kafka的消息协议是什么&#xff0c;怎么保证消息的可靠性和高性能传输的&#xff0c;接下来我们一同探究一下 Kafka 在不同的使用场景和组件交互中用到了多种协议&#xff0c;以下为你详细介绍&#xff1a; 内部通信协议 Kafka 使用…...

Vue 3 30天精进之旅:Day 09 - 组合式API

在Vue 3中&#xff0c;组合式API&#xff08;Composition API&#xff09;是一个引入的新特性&#xff0c;它为开发者提供了一种更灵活的方式来构建和组织组件。与传统的选项API相比&#xff0c;组合式API更注重逻辑的复用和逻辑的组合&#xff0c;让我们更容易处理大型应用中的…...

Day28(补)-【AI思考】-AI会不会考虑自己的需求?

文章目录 AI会不会考虑自己的需求&#xff1f;一、**技术本质&#xff1a;深度≠理解**二、**传播机制&#xff1a;热搜如何制造幻觉**三、**伦理考量&#xff1a;为何必须"撇清"**关键结论 AI会不会考虑自己的需求&#xff1f; 让思想碎片重焕生机的灵魂&#xff1a…...

JavaScript 进阶(下)

原型 what 首先&#xff0c;构造函数通过原型分配的函数是所有对象所 共享的。 然后&#xff0c;JavaScript 规定&#xff0c;每一个构造函数都有一个 prototype 属性&#xff0c;指向另一个对象&#xff0c;所以我们也称为原型对象 这个对象可以挂载函数&#xff0c;对象实…...

selenium自动化测试框架——面试题整理

目录 1. 什么是 Selenium&#xff1f;它的工作原理是什么&#xff1f; 2. Selenium 主要组件 3. 常见 WebDriver 驱动 4. Selenium 如何驱动浏览器&#xff1f; 5. WebDriver 协议是什么&#xff1f; 6. Page Object 模式与 Page Factory 7. 如何判断元素是否可见&#x…...

CF1098F Ж-function

【题意】 给你一个字符串 s s s&#xff0c;每次询问给你 l , r l, r l,r&#xff0c;让你输出 s s s l , r sss_{l,r} sssl,r​中 ∑ i 1 r − l 1 L C P ( s s i , s s 1 ) \sum_{i1}^{r-l1}LCP(ss_i,ss_1) ∑i1r−l1​LCP(ssi​,ss1​)。 【思路】 和前一道题一样&#…...

数据库备份、主从、集群等配置

数据库备份、主从、集群等配置 1 MySQL1.1 docker安装MySQL1.2 主从复制1.2.1 主节点配置1.2.2 从节点配置1.2.3 创建用于主从同步的用户1.2.4 开启主从同步1.2.4 主从同步验证 1.3 主从切换1.3.1 主节点设置只读&#xff08;在192.168.1.151上操作&#xff09;1.3.2 检查主从数…...

电脑要使用cuda需要进行什么配置

在电脑上使用CUDA&#xff08;NVIDIA的并行计算平台和API&#xff09;&#xff0c;需要进行以下配置和准备&#xff1a; 1. 检查NVIDIA显卡支持 确保你的电脑拥有支持CUDA的NVIDIA显卡。 可以在NVIDIA官方CUDA支持显卡列表中查看显卡型号是否支持CUDA。 2. 安装NVIDIA显卡驱动…...

【Unity3D】实现横版2D游戏——攀爬绳索(简易版)

目录 GeneRope.cs 场景绳索生成类 HeroColliderController.cs 控制角色与单向平台是否忽略碰撞 HeroClampController.cs 控制角色攀爬 OnTriggerEnter2D方法 OnTriggerStay2D方法 OnTriggerExit2D方法 Update方法 开始攀爬 结束攀爬 Sensor_HeroKnight.cs 角色触发器…...

JS 时间格式大全(含大量示例)

在 JS 中&#xff0c;处理时间和日期是常见的需求。无论是展示当前时间、格式化日期字符串&#xff0c;还是进行时间计算&#xff0c;JavaScript 都提供了丰富的 API 来满足这些需求。本文将详细介绍如何使用 JavaScript 生成各种时间格式&#xff0c;从基础到高级&#xff0c;…...

opencv裁剪视频区域

import cv2 # 打开视频文件 video_path input.mp4 cap cv2.VideoCapture(video_path) # 获取视频的帧率、宽度和高度 fps int(cap.get(cv2.CAP_PROP_FPS)) width int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)) height int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)) # 定义裁剪区…...

C++ deque(1)

1.deque介绍 deque的扩容不像vector那样麻烦 直接新开一个buffer 不用重新开空间再把数据全部移过去 deque本质上是一个指针数组和vector<vector>不一样&#xff0c;vector<vector>本质上是一个vector对象数组&#xff01;并且vector<vector>的buffer是不一…...

MapReduce概述

目录 1. MapReduce概述2. MapReduce的功能2.1 数据划分和计算任务调度2.2 数据/代码互定位2.3 系统优化2.4 出错检测和恢复 3. MapReduce处理流程4. MapReduce编程基础参考 1. MapReduce概述 MapReduce是面向大数据并行处理的计算模型、框架和平台:   1. 基于集群的高性能并行…...

DOM操作中childNodes与children的差异及封装方案

引言 在JavaScript的DOM操作中&#xff0c;childNodes和children是开发者常用的属性&#xff0c;但它们在浏览器中的行为差异可能导致兼容性问题。尤其是在处理空白符&#xff08;如换行符\n&#xff09;时&#xff0c;某些浏览器&#xff08;如Chrome和Edge&#xff09;会将空…...

在线课堂小程序设计与实现(LW+源码+讲解)

专注于大学生项目实战开发,讲解,毕业答疑辅导&#xff0c;欢迎高校老师/同行前辈交流合作✌。 技术范围&#xff1a;SpringBoot、Vue、SSM、HLMT、小程序、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容&#xff1a;…...

分布式系统架构怎么搭建?

分布式系统架构 互联网企业的业务飞速发展&#xff0c;促使系统架构不断变化。总体来说&#xff0c;系统架构大致经历了单体应用架构—垂直应用架构—分布式架构—SOA架构—微服务架构的演变&#xff0c;很多互联网企业的系统架构已经向服务化网格&#xff08;Service Mesh&am…...

大模型知识蒸馏技术(2)——蒸馏技术发展简史

版权声明 本文原创作者:谷哥的小弟作者博客地址:http://blog.csdn.net/lfdfhl2006年模型压缩研究 知识蒸馏的早期思想可以追溯到2006年,当时Geoffrey Hinton等人在模型压缩领域进行了开创性研究。尽管当时深度学习尚未像今天这样广泛普及,但Hinton的研究已经为知识迁移和模…...

C++初阶 -- 泛型编程(函数模板、类模板)入门

目录 一、泛型编程 1.1 介绍 二、函数模板 2.1 函数模板的概念 2.2 函数模板的格式 2.3 函数模板的原理 2.4 函数模板的实例化 2.4.1 隐式实例化 2.4.2 显式实例化 2.5 模板参数的匹配原则 三、类模板 3.1 类模板的使用格式 3.2 类模板的实例化 一、泛型编程 在有…...

[EAI-027] RDT-1B: a Diffusion Foundation Model for Bimanual Manipulation

Paper Card 论文标题&#xff1a;RDT-1B: a Diffusion Foundation Model for Bimanual Manipulation 论文作者&#xff1a;Songming Liu, Lingxuan Wu, Bangguo Li, Hengkai Tan, Huayu Chen, Zhengyi Wang, Ke Xu, Hang Su, Jun Zhu 论文链接&#xff1a;https://arxiv.org/ab…...

MongoDB常见的运维工具总结介绍

MongoDB 提供了一些强大的运维工具&#xff0c;帮助管理员进行数据库监控、备份、恢复、性能优化等操作。以下是一些常见的 MongoDB 运维工具及其功能介绍&#xff1a; 1. MongoDB Atlas 功能&#xff1a;MongoDB Atlas 是 MongoDB 官方的云托管数据库服务&#xff0c;它提供…...

dify实现原理分析-rag-数据检索的实现

数据检索的总体执行步骤 数据检索总体步骤如下&#xff1a; #mermaid-svg-YCRNdSE7T1d0Etyj {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-YCRNdSE7T1d0Etyj .error-icon{fill:#552222;}#mermaid-svg-YCRNdSE7T1d…...

20个整流电路及仿真实验汇总

0、 前言 以下是关于“20个整流电路及仿真实验汇总”的前言部分: 在现代电力电子技术领域,整流电路作为将交流电(AC)转换为直流电(DC)的关键电路,广泛应用于各类电源设计、信号处理以及电力电子设备中。整流电路不仅能够为电子设备提供稳定的直流电源,还在电力传输、…...

CVE-2020-0796永恒之蓝2.0(漏洞复现)

目录 前言 产生原因 影响范围 漏洞复现 复现环境 复现步骤 防御措施 总结 前言 在网络安全的战场上&#xff0c;漏洞一直是攻防双方关注的焦点。CVE-2020-0796&#xff0c;这个被称为 “永恒之蓝 2.0” 的漏洞&#xff0c;一度引起了广泛的关注与担忧。它究竟是怎样的…...

爬虫基础(一)HTTP协议 :请求与响应

前言 爬虫需要基础知识&#xff0c;HTTP协议只是个开始&#xff0c;除此之外还有很多&#xff0c;我们慢慢来记录。 今天的HTTP协议&#xff0c;会有助于我们更好的了解网络。 一、什么是HTTP协议 &#xff08;1&#xff09;定义 HTTP&#xff08;超文本传输协议&#xff…...

拼车(1094)

1094. 拼车 - 力扣&#xff08;LeetCode&#xff09; 解法&#xff1a; class Solution { public:bool carPooling(vector<vector<int>>& trips, int capacity) {uint32_t passenger_cnt 0;//将原数据按照from排序auto func_0 [](vector<int> & …...

Ubuntu全面卸载mysql

如果你已经看到whereis mysql输出了与MySQL相关的路径&#xff0c;说明MySQL仍然存在于系统中。要卸载MySQL&#xff0c;可以按照以下步骤操作&#xff0c;确保完全删除所有相关的文件和配置&#xff1a; 1. 停止MySQL服务 首先&#xff0c;停止MySQL服务&#xff1a; sudo …...

@Inject @Qualifier @Named

Inject Qualifier Named 在依赖注入&#xff08;DI&#xff09;中&#xff0c;Inject、Qualifier 和 Named 是用于管理对象创建和绑定的关键注解。以下是它们的用途、依赖配置和代码示例的详细说明&#xff1a; 1. 注解的作用 Inject&#xff1a;标记需要注入的构造函数、字段…...

OpenHarmonyOS 3.2 编译生成的hap和app文件的名称如何配置追加版本号?

找了一圈发现官方的文档都是最新的&#xff0c;3.2很多API都不支持&#xff0c;比如获取OhosAppContext&#xff0c;通过OhosAppContext来获取应用版本号&#xff0c;最终是通过读取app.json5的文件内容来读取版本号&#xff0c;最终修改entry下的hvigorfile.ts如下&#xff0c…...

初始化mysql报错cannot open shared object file: No such file or directory

报错展示 我在初始化msyql的时候报错&#xff1a;mysqld: error while loading shared libraries: libaio.so.1: cannot open shared object file: No such file or directory 解读&#xff1a; libaio包的作用是为了支持同步I/O。对于数据库之类的系统特别重要&#xff0c;因此…...

Vue.js组件开发-实现全屏背景图片滑动切换特效

使用 Vue 实现全屏背景图片滑动切换特效的详细步骤、代码、注释和使用说明。 步骤 创建 Vue 项目&#xff1a;使用 Vue CLI 创建一个新的 Vue 项目。准备图片资源&#xff1a;准备好要用于背景切换的图片&#xff0c;并将它们放在项目的合适目录下。编写 HTML 结构&#xff1…...

AI在自动化测试中的伦理挑战

在软件测试领域&#xff0c;人工智能&#xff08;AI&#xff09;已经不再是遥不可及的未来技术&#xff0c;而是正在深刻影响着测试过程的现实力量。尤其是在自动化测试领域&#xff0c;AI通过加速测试脚本生成、自动化缺陷检测、测试数据生成等功能&#xff0c;极大提升了测试…...

FreeRTOS的任务创建和删除

1&#xff0c;任务创建和删除的API函数 任务的创建和删除本质就是调用FreeRTOS的API函数 动态创建任务&#xff1a; 任务的任务控制块以及任务的栈空间所需的内存&#xff0c;均由 FreeRTOS 从 FreeRTOS 管理的堆中分配。 静态创建任务&#xff1a; 任务的任务控制块以及任务的…...

【C++】STL容器使用与实现详解:vector

文章目录 Ⅰ. vector的介绍和使用一、vector的介绍二、vector的使用 &#xff08;只列出比较重要的&#xff0c;其他的需要时查文档&#xff09;1. vector的定义2. vector iterator&#xff08;迭代器&#xff09;的使用3. vector 容量问题4. vector 增删查改5. 正确释放 vecto…...

【Block总结】动态蛇形卷积,专注于细长和弯曲的局部结构|即插即用

论文信息 标题: Dynamic Snake Convolution based on Topological Geometric Constraints for Tubular Structure Segmentation 作者: 戚耀磊、何宇霆、戚晓明、张媛、杨冠羽 会议: 2023 IEEE/CVF International Conference on Computer Vision (ICCV) 发表时间: 2023年10月…...

物业管理软件引领社区智能化转型提升服务效率与居民生活质量

内容概要 物业管理软件的出现&#xff0c;标志着社区管理方式的一场革命&#xff0c;它不仅仅是一个工具&#xff0c;更是推动智能化转型的关键助力。通过高效的管理功能&#xff0c;物业管理软件在优化服务流程的同时&#xff0c;也提升了居民的生活质量和社区的整体发展活力…...

论文阅读(十三):复杂表型关联的贝叶斯、基于系统的多层次分析:从解释到决策

1.论文链接&#xff1a;Bayesian, Systems-based, Multilevel Analysis of Associations for Complex Phenotypes: from Interpretation to Decision 摘要&#xff1a; 遗传关联研究&#xff08;GAS&#xff09;报告的结果相对稀缺&#xff0c;促使许多研究方向。尽管关联概念…...

线性调整器——耗能型调整器

线性调整器又称线性电压调节器&#xff0c;以下是关于它的介绍&#xff1a; 基本工作原理 线性调整器的基本电路如图1.1(a)所示,晶体管Q1(工作于线性状态,或非开关状态)构成一个连接直流源V和输出端V。的可调电气电阻,直流源V由60Hz隔离变压器&#xff08;电气隔离和整流&#…...

梯度提升用于高效的分类与回归

使用 决策树&#xff08;Decision Tree&#xff09; 实现 梯度提升&#xff08;Gradient Boosting&#xff09; 主要是模拟 GBDT&#xff08;Gradient Boosting Decision Trees&#xff09; 的原理&#xff0c;即&#xff1a; 第一棵树拟合原始数据计算残差&#xff08;负梯度…...

使用Ollama和Open WebUI快速玩转大模型:简单快捷的尝试各种llm大模型,比如DeepSeek r1

Ollama本身就是非常优秀的大模型管理和推理组件&#xff0c;再使用Open WebUI更加如虎添翼&#xff01; Ollama快速使用指南 安装Ollama Windows下安装 下载Windows版Ollama软件&#xff1a;Release v0.5.7 ollama/ollama GitHub 下载ollama-windows-amd64.zip这个文件即可…...

2025年1月个人工作生活总结

本文为 2025年1月工作生活总结。 研发编码 使用sqlite3命令行查询表数据 可以直接使用sqlite3查询数据表&#xff0c;不需进入命令行模式。示例如下&#xff1a; sqlite3 database_name.db "SELECT * FROM table_name;"linux shell使用read超时一例 先前有个编译…...

Windows环境安装nvm,并使用nvm管理nodejs版本教程

目录 1.nvm安装步骤 2.验证nvm是否安装成功 3.查看本地可以安装的所有版本 4.安装特定nodejs版本 5.配置nvm镜像 6.使用特定nodejs版本 7.给nodejs配置镜像和环境变量 8.查看本地安装的所有版本(* 表示当前版本) 9.卸载指定版本的nodejs 前端开发中&#xff0c;不…...

C++中常用的排序方法之——冒泡排序

成长路上不孤单&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a;&#x1f60a; 【14后&#x1f60a;///计算机爱好者&#x1f60a;///持续分享所学&#x1f60a;///如有需要欢迎收藏转发///&#x1f60a;】 今日分享关于C中常用的排序方法之——冒泡排序的…...