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

自定义Java注解及其应用

上一篇博客:Java注解

 写在前面:大家好!我是晴空๓。如果博客中有不足或者的错误的地方欢迎在评论区或者私信我指正,感谢大家的不吝赐教。我的唯一博客更新地址是:https://ac-fun.blog.csdn.net/。非常感谢大家的支持。一起加油,冲鸭!
用知识改变命运,用知识成就未来!加油 (ง •̀o•́)ง (ง •̀o•́)ง

文章目录

  • 前言
  • 自定义注解
    • 成员变量
    • 初始值
    • 注解的元注解使用
    • 注解与反射的关系
  • 自定义注解结合反射示例
    • 自定义AutoFill注解
      • 数据库操作类型枚举类
      • AutoFill注解
    • 自定义切面类
      • 代码优化

前言

 在上一篇 Java注解 中主要写了注解的一些示例以及注解的组成,本篇主要介绍一下如何自定义注解以及如何将自定义的注解结合反射进行使用。

自定义注解

 通过上一篇博客Java注解中 注解的组成 部分就可以知道我们如何自定义注解了。但是自定义注解还有一些需要注意的点,主要如下:

成员变量

Annotation成员变量以无参数方法形式来声明,方法名和返回值定义了该成员变量的名字和类型。类型只能是八种基本数据类型(byte、short、int、long、float、double、char、boolean)、String类型、Class类型、enum类型、Annotation类型以及以上所有类型的数组

初始值

 可以在定义成员变量时为其指定初始值,指定成员变量的初始值可以用 default关键字

public @interface MyAnnotation {int value() default 10;
}

注解的元注解使用

 合理的使用注解的元注解,通过元注解指定注解的保留策略以及注解可以应用的目标位置,详见上一篇博客Java注解。

注解与反射的关系

 只有当注解的保留策略为 @Retention(RetentionPolicy.RUNTIME) 时,才能在运行时通过反射获取注解信息。

反射操作(如获取类的字段、方法,调用方法等)比直接的Java代码调用要慢很多。每次通过反射获取注解信息或者执行注解相关的操作,都需要进行额外的类型检查、权限验证等步骤。 例如,频繁地使用反射来检查一个类的所有方法上是否有某个注解,并根据注解来执行不同的逻辑,在高并发或者对性能要求极高的场景下,可能会成为性能瓶颈。

 如果注解的处理逻辑对性能影响较大,可以考虑缓存反射操作的结果。或者在系统启动时,预先加载并处理好所有需要通过注解进行操作的类和方法信息。

自定义注解结合反射示例

 之前看尚硅谷的苍穹外卖中就有一个合适的例子,这里简单写一下并附上当时的笔记。假设我们的项目中有很多张表都具有相同的创建时间、修改时间、创建人id、修改人id这几个公共字段,我们希望将这些初始化代码统一放在一个地方进行处理以减少冗余代码同时也可以更方便的维护。这就需要我们使用注解进行标注什么时候应该调用公共的初始化方法进行相关的初始化操作,同时也需要利用反射为公共字段赋值。以下是详细的实现步骤。

自定义AutoFill注解

 首先定义一个用于标识什么时候调用相关初始化代码的注解 AutoFill,该注解有一个字段表示是插入操作还是修改操作,我们需要这个标识进行判断初始化的时候是只初始化创建时间和创建人id,还是都需要初始化。

数据库操作类型枚举类

/*** 数据库操作类型枚举*/
public enum OperationType {/*** 更新操作*/UPDATE,/*** 插入操作*/INSERT}

AutoFill注解

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 AutoFill {// 数据库操作类型:UPDATE-更新 INSERT-插入OperationType value();
}

自定义切面类

 定义好注解之后需要使用反射获取注解的信息并进行相应的处理,使用切面类进行拦截。

import com.sky.annotation.AutoFill;
import com.sky.context.BaseContext;
import com.sky.enumeration.OperationType;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;import java.lang.reflect.Method;
import java.time.LocalDateTime;/*** 自定义切面实现公共处理逻辑*/
@Aspect
@Component
@Slf4j
public class AutoFillAspect {/*** 定义切入点* 1. execution:最长用的 PCD(切入点标识符),用来匹配特定方法的执行,具体参数如下:*      execution([修饰符] <返回类型> [全限定类名.]<方法>(<参数>) [异常])*      这其中每一部分都可以使用 * 通配符, []表示选输 <>表示必输*      类名中使用 .* 表示包中的所有类, ..* 表示当前包与子包中的所有类*      参数主要分为以下几种情况:*          - () 表示方法五参数*          - (..) 表示有任意个参数*          - (*) 表示有一个任意类型的参数*          - (String) 表示有一个 String 类型的参数*          - (String, String) 表示有两个 String 类型的参数** 2. 如果类上面带了注解,也可以用以下 PCD*      - @target 指定的目标对象带有特定类型的注解*      - @args 传入的方法参数带有特定类型的注解*      - @annotation 拦截的方法上带有特定类型的注解*/@Pointcut("execution(* com.sky.mapper.*.*(..)) && @annotation(com.sky.annotation.AutoFill)")public void autoFillPointCut(){}/*** 前置通知* @param joinPoint 连接点*      JoinPoint 表示程序执行过程中的一个连接点,通常是方法的调用。*      JoinPoint 提供了关于当前连接点的详细信息,这些信息可以用于在通知(Advice)中进行各种操作,*                  如日志记录、参数检查、性能监控等。**/@Before("autoFillPointCut()")public void autoFill(JoinPoint joinPoint) {log.info("开始进行公共字段自动填充[{}]", joinPoint);// 获取当前被拦截方法上@AutoFill()中的数据库操作类型/** 获取方法的签名对象*       getSignature() 是 JoinPoint 接口中的一个方法,用于获取当前连接点的签名。*    签名包含了方法的名称、参数类型和返回类型等信息。Signature 接口提供了多种方法,可以用来获取这些详细信息*    joinPoint.getSignature() 返回的 Signature 对象可以强制转换为几种类型,具体取决于当前连接点的类型,在Spring AOP 中*    最常见的类型是 MethodSignature, MethodSignature 是 Signature 的一个子接口,用于表示方法执行的连接点。*    它提供了更多关于方法的详细信息,如参数名称、参数类型、返回类型等。除了该类型还有 ConstructorSignature(构造器连接点)*    和 FieldSignature(字段访问连接点)*      MethodSignature 常用方法如下:*          - String getName():返回方法的名称。*          - Class<?> getDeclaringType():返回声明该方法的类。*          - Class<?> getReturnType():返回方法的返回类型。*          - Class<?>[].getParameterTypes():返回方法的参数类型数组。*          - String[].getParameterNames():返回方法的参数名称数组。*          - Method getMethod():返回 java.lang.reflect.Method 对象。**/MethodSignature signature = (MethodSignature) joinPoint.getSignature();// 获取方法上的注解对象AutoFill autoFill = signature.getMethod().getAnnotation(AutoFill.class);// 获取数据库操作类型OperationType operationType = autoFill.value();// 获取被拦截方法的参数(约定实体为第一个参数)/*joinPoint.getArgs() 方法是 JoinPoint 接口中的一个方法,用于获取当前连接点(通常是方法调用)的参数数组。这个方法返回一个 Object[] 类型的数组,其中每个元素对应方法调用的一个参数。*/Object[] args = joinPoint.getArgs();if (args == null || args.length == 0) {return;}// 获取方法的第一个参数及实体对象Object entity = args[0];// 为参数中的对象的公共属性进行赋值LocalDateTime now = LocalDateTime.now();Long currentId = BaseContext.getCurrentId();if (operationType == OperationType.INSERT) {try {// 通过反射获取实体类中的相关set方法// 通过反射获取指定名称和参数类型的已声明方法Method setCreatTime = entity.getClass().getDeclaredMethod("setCreatTime", LocalDateTime.class);Method setCreateUser = entity.getClass().getDeclaredMethod("setCreateUser", Long.class);Method setUpdateTime = entity.getClass().getDeclaredMethod("setUpdateTime", LocalDateTime.class);Method setUpdateUser = entity.getClass().getDeclaredMethod("setUpdateUser", Long.class);// 通过反射为对象属性赋值setCreatTime.invoke(entity, now);setCreateUser.invoke(entity, currentId);setUpdateTime.invoke(entity, now);setUpdateUser.invoke(entity, currentId);} catch (Exception e) {throw new RuntimeException(e);}} else if (operationType == OperationType.UPDATE) {try {// 通过反射获取实体类中的相关set方法// 通过反射获取指定名称和参数类型的已声明方法Method setUpdateTime = entity.getClass().getDeclaredMethod("setUpdateTime", LocalDateTime.class);Method setUpdateUser = entity.getClass().getDeclaredMethod("setUpdateUser", Long.class);// 通过反射为对象属性赋值setUpdateTime.invoke(entity, now);setUpdateUser.invoke(entity, currentId);} catch (Exception e) {throw new RuntimeException(e);}}}}

 可以通过打断点的方式看一下 joinPoint 连接点 里面的具体内容都是什么。
连接点的具体内容

代码优化

 上面是之前老师写的代码以及自己的学习笔记,其实这个代码可以再优化一下。优化的思路主要有两个方面一个是对性能方面的优化这个是主要的,另一点是代码优化将重复的代码封装一下并将公共逻辑拆分出来以便更好的维护。

 性能优化主要在于反射调用可能会对性能产生一定影响,特别是在方法调用频繁的情况下。我们可以使用缓存来存储方法对象,每次调用时都使用反射获取相关信息,而是在缓存中进行查找。这里用一个 Map<String, Method> 来作为缓存池,并将其初始化为一个 ConcurrentHashMap 实例。

 使用 ConcurrentHashMap 的主要原因是它提供了线程安全的哈希表实现,适用于多线程环境。在多线程应用中,多个线程可能会同时访问和修改哈希表,如果没有适当的同步机制,可能会导致数据不一致、并发修改异常等问题。ConcurrentHashMap 通过内部的锁分段机制来确保线程安全,同时提供了较高的并发性能。HashMap 不是线程安全的,多个线程同时写入时可能会导致数据不一致。而 Hashtable 虽然线程安全,但它是通过 synchronized 方法实现的,这会导致整个表在每次操作时都被锁定,性能较差。

优化之后的完整代码:

import com.sky.annotation.AutoFill;
import com.sky.context.BaseContext;
import com.sky.enumeration.OperationType;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;import java.lang.reflect.Method;
import java.time.LocalDateTime;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;@Aspect
@Component
@Slf4j
public class AutoFillAspectPlus {/*** 缓存方法对象*/private final Map<String, Method> methodCache = new ConcurrentHashMap<>();@Pointcut("execution(* com.sky.mapper.*.*(..)) && @annotation(com.sky.annotation.AutoFill)")public void autoFillPointCut(){}@Before("autoFillPointCut()")public void autoFill(JoinPoint joinPoint) {log.info("开始进行公共字段自动填充Plus版[{}]", joinPoint.toShortString());MethodSignature signature = (MethodSignature) joinPoint.getSignature();AutoFill autoFill = signature.getMethod().getAnnotation(AutoFill.class);OperationType operationType = autoFill.value();Object[] args = joinPoint.getArgs();if (args == null || args.length == 0) {return;}Object entity = args[0];LocalDateTime now = LocalDateTime.now();Long currentId = BaseContext.getCurrentId();if (operationType == OperationType.INSERT) {setFieldValue(entity, "setCreateTime", now);setFieldValue(entity, "setCreateUser", currentId);setFieldValue(entity, "setUpdateTime", now);setFieldValue(entity, "setUpdateUser", currentId);log.info("初始化完毕[{}]", entity);} else if (operationType == OperationType.UPDATE) {setFieldValue(entity, "setUpdateTime", now);setFieldValue(entity, "setUpdateUser", currentId);log.info("初始化完毕[{}]", entity);}}/*** 设置实体对象中某个字段的值* @param entity 实体对象* @param methodName 字段名称* @param value 字段的值*/private void setFieldValue(Object entity, String methodName, Object value) {try {Method method = getMethod(entity, methodName, value.getClass());log.info("获取到method为[{}]", method.getName());method.invoke(entity, value);} catch (Exception e) {log.error("初始化字段异常: [{}]", methodName, e);throw new RuntimeException(e);}}/*** 查找指定名称和参数类型的方法* @param entity 实体* @param methodName set方法* @param parameterType 参数类型* @return 相关set方法*/private Method getMethod(Object entity, String methodName, Class<?> parameterType) {// 获得方法的名称,使用 类名.方法名 作为keyString key = entity.getClass().getName() + "." + methodName;log.info("获取当前key[{}]的值", key);/*computeIfAbsent 方法是 ConcurrentHashMap 的一个方法,它接受一个键和一个函数。如果缓存中已经存在这个键,它会返回缓存中的值;如果不存在,它会执行提供的函数,将结果存储在缓存中,并返回这个结果。确保方法对象的查找和缓存操作是线程安全的。*/return methodCache.computeIfAbsent(key, k -> {try {return entity.getClass().getDeclaredMethod(methodName, parameterType);} catch (NoSuchMethodException e) {log.error("方法未找到: [{}]", methodName, e);throw new RuntimeException(e);}});}}

相关文章:

自定义Java注解及其应用

上一篇博客&#xff1a;Java注解 写在前面&#xff1a;大家好&#xff01;我是晴空๓。如果博客中有不足或者的错误的地方欢迎在评论区或者私信我指正&#xff0c;感谢大家的不吝赐教。我的唯一博客更新地址是&#xff1a;https://ac-fun.blog.csdn.net/。非常感谢大家的支持。…...

回归预测 | MATLAB实GRU多输入单输出回归预测

回归预测 | MATLAB实GRU多输入单输出回归预测 目录 回归预测 | MATLAB实GRU多输入单输出回归预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 回归预测 | MATLAB实GRU多输入单输出回归预测。使用GRU作为RNN的一种变体来处理时间序列数据。GRU相比传统的RNN有较好的记…...

ISP流程--去马赛克详解

前言 本期我们将深入讨论ISP流程中的去马赛克处理。我们熟知&#xff0c;彩色图像由一个个像元组成&#xff0c;每个像元又由红、绿、蓝&#xff08;RGB&#xff09;三通道构成。而相机传感器只能感知光的强度&#xff0c;无法直接感知光谱信息&#xff0c;即只有亮暗而没有颜色…...

用户注册模块用户校验(头条项目-05)

1 用户注册后端逻辑 1.1 接收参数 username request.POST.get(username) password request.POST.get(password) phone request.POST.get(phone) 1.2 校验参数 前端校验过的后端也要校验&#xff0c;后端的校验和前端的校验是⼀致的 # 判断参数是否⻬全 # 判断⽤户名是否…...

【大数据】Apache Superset:可视化开源架构

Apache Superset是什么 Apache Superset 是一个开源的现代化数据可视化和数据探索平台&#xff0c;主要用于帮助用户以交互式的方式分析和展示数据。有不少丰富的可视化组件&#xff0c;可以将数据从多种数据源&#xff08;如 SQL 数据库、数据仓库、NoSQL 数据库等&#xff0…...

如何搭建 Vue.js 开源项目的 CI/CD 流水线

网罗开发 &#xff08;小红书、快手、视频号同名&#xff09; 大家好&#xff0c;我是 展菲&#xff0c;目前在上市企业从事人工智能项目研发管理工作&#xff0c;平时热衷于分享各种编程领域的软硬技能知识以及前沿技术&#xff0c;包括iOS、前端、Harmony OS、Java、Python等…...

OCR文字识别—基于PP-OCR模型实现ONNX C++推理部署

概述 PaddleOCR 是一款基于 PaddlePaddle 深度学习平台的开源 OCR 工具。PP-OCR是PaddleOCR自研的实用的超轻量OCR系统。它是一个两阶段的OCR系统&#xff0c;其中文本检测算法选用DB&#xff0c;文本识别算法选用CRNN&#xff0c;并在检测和识别模块之间添加文本方向分类器&a…...

国产3D CAD将逐步取代国外软件

在工业软件的关键领域&#xff0c;计算机辅助设计&#xff08;CAD&#xff09;软件对于制造业的重要性不言而喻。近年来&#xff0c;国产 CAD 的发展态势迅猛&#xff0c;展现出巨大的潜力与机遇&#xff0c;正逐步改变着 CAD 市场长期由国外软件主导的格局。 国产CAD发展现状 …...

GoLand 如何集成 Netty?

目录 1.回答问题&#xff1a; 2.以下是实现类似 Netty 功能的步骤&#xff1a; 2.1 实现基本的网络通信功能&#xff1a; 3. 使用 Go 的第三方库实现 Netty 功能 4.实现类似 Netty 的事件循环&#xff1a; 5. 运用场景&#xff1a; 1.回答问题&#xff1a; 要在 GoLand 中…...

C++中 为什么要把基类指针指向子类对象?

为什么要把基类指针指向子类对象&#xff1f; 1&#xff09;实现多态性 动态绑定行为&#xff1a;通过基类指针指向子类对象&#xff0c;可以利用 C 的多态机制。当基类中有虚函数&#xff0c;并且子类重写了这些虚函数时&#xff0c;通过基类指针调用虚函数&#xff0c;实际调…...

2025年第三届“华数杯”国际赛A题解题思路与代码(Matlab版)

游泳竞技策略优化模型代码详解&#xff08;MATLAB版&#xff09; 第一题&#xff1a;速度优化模型 本部分使用MATLAB实现游泳运动员在不同距离比赛中的速度分配策略优化。 1. 模型概述 模型包含三个主要文件&#xff1a; speed_optimization.m: 核心优化类plot_speeds.m: …...

做一个 简单的Django 《股票自选助手》显示 用akshare 库(A股数据获取)

图&#xff1a; 股票自选助手 这是一个基于 Django 开发的 A 股自选股票信息查看系统。系统使用 akshare 库获取实时股票数据&#xff0c;支持添加、删除和更新股票信息。 功能特点 支持添加自选股票实时显示股票价格和涨跌幅一键更新所有股票数据支持删除不需要的股票使用中…...

深入探索 ScottPlot.WPF:在 Windows 桌面应用中绘制精美图表的利器

一、ScottPlot.WPF 简介 ScottPlot.WPF 是基于 ScottPlot 绘图库专门为 Windows Presentation Foundation (WPF) 框架量身定制的强大绘图组件。它无缝集成到 WPF 应用程序中,为开发者提供了一种简洁、高效的方式来可视化数据,无论是科学研究中的实验数据展示、金融领域的行情…...

Spring bean的生命周期和扩展

接AnnotationConfigApplicationContext流程看实例化的beanPostProcessor-CSDN博客&#xff0c;以具体实例看bean生命周期的一些执行阶段 bean生命周期流程 生命周期扩展处理说明实例化:createBeanInstance 构造方法&#xff0c; 如Autowired的构造方法注入依赖bean 如UserSer…...

【Docker】docker compose 安装 Redis Stack

注&#xff1a;整理不易&#xff0c;请不要吝啬你的赞和收藏。 前文 Redis Stack 什么是&#xff1f; 简单来说&#xff0c;Redis Stack 是增强版的 Redis &#xff0c;它在传统的 Redis 数据库基础上增加了一些高级功能和模块&#xff0c;以支持更多的使用场景和需求。Redis…...

Life Long Learning(李宏毅)机器学习 2023 Spring HW14 (Boss Baseline)

1. 终身学习简介 神经网络的典型应用场景是,我们有一个固定的数据集,在其上训练并获得模型参数,然后将模型应用于特定任务而无需进一步更改模型参数。 然而,在许多实际工程应用中,常见的情况是系统可以不断地获取新数据,例如 Web 应用程序中的新用户数据或自动驾驶中的…...

JavaEE之线程池

前面我们了解了多个任务可以通过创建多个线程去处理&#xff0c;达到节约时间的效果&#xff0c;但是每一次的线程创建和销毁也是会消耗计算机资源的&#xff0c;那么我们是否可以将线程进阶一下&#xff0c;让消耗计算机的资源尽可能缩小呢&#xff1f;线程池可以达到此效果&a…...

错误修改系列---基于RNN模型的心脏病预测(pytorch实现)

前言 前几天发布了pytorch实现&#xff0c;TensorFlow实现为&#xff1a;基于RNN模型的心脏病预测(tensorflow实现)&#xff0c;但是一处繁琐地方 一处错误&#xff0c;这篇文章进行修改&#xff0c;修改效果还是好了不少&#xff1b;源文章为&#xff1a;基于RNN模型的心脏病…...

修改之前的代码使得利用设备树文件和Platform总线设备驱动实现对多个LED的驱动【只是假想对LED进行驱动,并没有实际的硬件操作】

引言 在下面这篇博文中&#xff1a; 利用Linux的Platform总线设备驱动实现对多个LED的驱动【只是假想对LED进行驱动,并没有实际的硬件操作】 我们利用Platform总线设备驱动的思想实现了对多个LED的驱动。 Platform总线设备驱动以及其它的总线设备驱动都将驱动分成了三个部分…...

从CentOS到龙蜥:企业级Linux迁移实践记录(龙蜥开局)

引言&#xff1a; 在我们之前的文章中&#xff0c;我们详细探讨了从CentOS迁移到龙蜥操作系统的基本过程和考虑因素。今天&#xff0c;我们将继续这个系列&#xff0c;重点关注龙蜥系统的实际应用——特别是常用软件的安装和配置。 龙蜥操作系统&#xff08;OpenAnolis&#…...

多云架构,JuiceFS 如何实现一致性与低延迟的数据分发

随着大模型的普及&#xff0c;GPU 算力成为稀缺资源&#xff0c;单一数据中心或云区域的 GPU 资源常常难以满足用户的全面需求。同时&#xff0c;跨地域团队的协作需求也推动了企业在不同云平台之间调度数据和计算任务。多云架构正逐渐成为一种趋势&#xff0c;然而该架构下的数…...

Jenkins持续集成与交付安装配置

Jenkins 是一款开源的持续集成&#xff08;CI&#xff09;和持续交付&#xff08;CD&#xff09;工具&#xff0c;它主要用于自动化软件的构建、测试和部署流程。为项目持续集成与交付功能强大的应用。下面我们来介绍下它的安装与配置。 环境准备 更新系统组件&#xff08;这…...

十大排序简介

十大排序简介 一、排序分类二、排序思路1&#xff0e;冒泡排序&#xff08;Bubble Sort&#xff09;2&#xff0e;选择排序&#xff08;Selection Sort&#xff09;3&#xff0e;插入排序&#xff08;Insertion Sort&#xff09;4&#xff0e;希尔排序&#xff08;Shell Sort&a…...

uniapp小程序中隐藏顶部导航栏和指定某页面去掉顶部导航栏小程序

uniappvue3开发小程序过程中隐藏顶部导航栏和指定某页面去掉顶部导航栏方法 在page.json中 "globalStyle": {"navigationStyle":"custom",}, 如果是指定某个页面关闭顶部导航栏&#xff0c;在style中添加"navigationStyle": "cus…...

echarts:dataZoom属性横向滚动条拖拽不生效

问&#xff1a; 拖拽的过程中&#xff0c;第一次向右拖拽正常&#xff0c;然后就报错&#xff1a; echarts报错&#xff1a; var pointerOption pointerShapeBuilder[axisPointerType](axis,pixeValue,otherExtent),(axis,pixeValue,otherExtent)下划线红色报错&#xff1a;…...

【Leetcode 热题 100】739. 每日温度

问题背景 给定一个整数数组 t e m p e r a t u r e s temperatures temperatures&#xff0c;表示每天的温度&#xff0c;返回一个数组 a n s w e r answer answer&#xff0c;其中 a n s w e r [ i ] answer[i] answer[i] 是指对于第 i i i 天&#xff0c;下一个更高温度…...

R数据分析:多分类问题预测模型的ROC做法及解释

有同学做了个多分类的预测模型,结局有三个类别,做的模型包括多分类逻辑回归、随机森林和决策树,多分类逻辑回归是用ROC曲线并报告AUC作为模型评估的,后面两种模型报告了混淆矩阵,审稿人就提出要统一模型评估指标。那么肯定是统一成ROC了,刚好借这个机会给大家讲讲ROC在多…...

如何用 SSH 访问 QNX 虚拟机

QNX 虚拟机默认是开启 SSH 服务的&#xff0c;如果要用 SSH 访问 QNX 虚拟机&#xff0c;就需要知道虚拟机的 IP 地址&#xff0c;用户和密码。本文我们来看看如何获取这些参数。 1. 启动虚拟机 启动过程很慢&#xff0c;请耐心等待。 2. 查看 IP 地址 等待 IDE 连接到虚拟机。…...

交响曲-24-3-单细胞CNV分析及聚类

CNV概述 小于1kb是常见的插入、移位、缺失等的变异 人体内包含<10% 的正常CNV&#xff0c;我们的染色体数是两倍体&#xff0c;正常情况下&#xff0c;只有一条染色体表达&#xff0c;另一条沉默&#xff0c;当表达的那条染色体发生CNV之后&#xff0c;表达数量就会成倍增加…...

java远程调试debug

文章目录 首先被调试的服务配置idea 中配置远程调试连接上被调试服务打断点开始调试 首先被调试的服务配置 被调试的 java 服务需要开启允许被远程调试的配置&#xff0c;具体就是启动脚本中&#xff0c;加上允许被远程调试以及相应端口 # 针对JDK15.-1.8 -agentlib:jdwptran…...

操作系统之系统调用

系统调用 从上文简介得知&#xff0c;操作系统是计算机硬件和软件之间的桥梁&#xff0c;通过管理计算机软件和硬件资源&#xff0c;最终为我们用户提供服务。就如同一个管家帮助我们对CPU&#xff08;进程&#xff09;的管理、内存的管理、设备的管理、文件的管理。而我们如何…...

【docker】exec /entrypoint.sh: no such file or directory

dockerfile生成的image 报错内容&#xff1a; exec /entrypoint.sh: no such file or directory查看文件正常在此路径&#xff0c;但是就是报错没找到。 可能是因为sh文件的换行符使用了win的。...

CAPL概述与环境搭建

CAPL概述与环境搭建 目录 CAPL概述与环境搭建1. CAPL简介与应用领域1.1 CAPL简介1.2 CAPL的应用领域 2. CANoe/CANalyzer 安装与配置2.1 CANoe/CANalyzer 简介2.2 安装CANoe/CANalyzer2.2.1 系统要求2.2.2 安装步骤 2.3 配置CANoe/CANalyzer2.3.1 配置CAN通道2.3.2 配置CAPL节点…...

ML-Agents:智能体(三)

注&#xff1a;本文章为官方文档翻译&#xff0c;如有侵权行为请联系作者删除 Agent - Unity ML-Agents Toolkit–原文链接> ML-Agents&#xff1a;智能体&#xff08;一&#xff09; ML-Agents&#xff1a;智能体&#xff08;二&#xff09; ML-Agents&#xff1a;智能体&a…...

【harbor】离线安装2.9.0-arm64架构服务制作和升级部署

执行: .prepare 【作用就是产生一些配置信息 和docker-compose.yaml文件&#xff0c;然后docker-compose发布docker】 harbor官网地址&#xff1a;Harbor 参考文档可以看这里&#xff1a;部署 harbor 2.10.1 arm64 - 简书。 前提环境准备&#xff1a; 安装docker 和 docker…...

可视化-Visualization

可视化-Visualization 1.Introduction Visualization in Open CASCADE Technology is based on the separation of: on the one hand – the data which stores the geometry and topology of the entities you want to display and select, andon the other hand – its pr…...

完整化安装kubesphere,ks-jenkins的状态一直为init

错误描述&#xff1a; 打印日志&#xff1a; kubectl describe pod ks-jenkins-7fcff7857b-gh4g5 -n kubesphere-devops-system 日志描述如下&#xff1a; Events: Type Reason Age From Message ---- ------ ---- …...

halcon三维点云数据处理(十)locate_cylinder_3d

目录 一、locate_cylinder_3d例程代码二、gen_binocular_rectification_map函数三、binocular_disparity函数四、自定义函数select_best_candidates五、自定义函数remove_shadowed_regions 一、locate_cylinder_3d例程代码 1、读取或者创建3D形状模型&#xff0c; 2、根据双目…...

【CSS】设置滚动条样式

文章目录 基本语法用法案例 基本语法 在CSS中&#xff0c;可以使用 ::-webkit-scrollbar 和相关伪元素来为滚动条设置样式&#xff0c;但请注意这些伪元素是非标准的&#xff0c;主要用于WebKit内核浏览器&#xff08;如Chrome、Safari&#xff09;。 ::-webkit-scrollbar CSS …...

一个运行在浏览器中的开源Web操作系统Puter本地部署与远程访问

文章目录 前言1.关于Puter2.本地部署Puter3.Puter简单使用4. 安装内网穿透5.配置puter公网地址6. 配置固定公网地址 &#x1f4a1; 推荐 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。【点击跳转到网站…...

支持selenium的chrome driver更新到131.0.6778.264

最近chrome释放新版本&#xff1a;131.0.6778.264 如果运行selenium自动化测试出现以下问题&#xff0c;是需要升级chromedriver才可以解决的。 selenium.common.exceptions.SessionNotCreatedException: Message: session not created: This version of ChromeDriver only s…...

conda+jupyter+pycharm:如何在Windows conda环境下运行jupyter并使用浏览器或者pycharm运行.ipynb

1 安装conda 2 conda环境下安装jupyter pip install jupyter3 设置jupyter配置文件 1&#xff09;创建 jupyter_notebook_config.py文件 jupyter notebook --generate-config 2&#xff09;设置密码 3&#xff09;设置参数 直接将以下参数修改为自己的配置后复制到配置文件…...

生成式数据增强在大语言模型中的应用与实践

引言 近年来&#xff0c;大语言模型&#xff08;Large Language Models, LLMs&#xff09;如GPT、BERT等在自然语言处理&#xff08;NLP&#xff09;领域取得了巨大突破。然而&#xff0c;这些模型的性能往往依赖于大量高质量的训练数据&#xff0c;而在许多实际应用场景中&am…...

深度学习笔记11-优化器对比实验(Tensorflow)

&#x1f368; 本文为&#x1f517;365天深度学习训练营中的学习记录博客&#x1f356; 原作者&#xff1a;K同学啊 目录 一、导入数据并检查 二、配置数据集 三、数据可视化 四、构建模型 五、训练模型 六、模型对比评估 七、总结 一、导入数据并检查 import pathlib,…...

汽车免拆诊断 | 2007款保时捷Carrera S车行驶中发动机冷却液温度报警灯异常点亮

故障现象 一辆2007款保时捷Carrera S车&#xff0c;搭载3.8 L自然吸气发动机&#xff0c;累计行驶里程约为7.8万km。车主反映&#xff0c;车辆行驶一段距离后&#xff0c;组合仪表上的发动机冷却液温度报警灯异常点亮。为此&#xff0c;在其他维修厂已更换过节温器、发动机冷却…...

【蓝牙】win11 笔记本电脑连接 hc-06

文章目录 前言步骤 前言 使用电脑通过蓝牙添加串口 步骤 设置 -> 蓝牙和其他设备 点击 显示更多设备 更多蓝牙设置 COM 端口 -> 添加 有可能出现卡顿&#xff0c;等待一会 传出 -> 浏览 点击添加 hc-06&#xff0c;如果没有则点击 再次搜索 确定 添加成…...

what?ngify 比 axios 更好用,更强大?

文章目录 前言一、什么是ngify&#xff1f;二、npm安装三、发起请求3.1 获取 JSON 数据3.2 获取其他类型的数据3.3 改变服务器状态3.4 设置 URL 参数3.5 设置请求标头3.6 与服务器响应事件交互3.7 接收原始进度事件3.8 处理请求失败3.9 Http Observables 四、更换 HTTP 请求实现…...

EFCore HasDefaultValueSql (续2 HasComputedColumnSql)

前情&#xff1a;EFCore HasDefaultValueSql EFCore HasDefaultValueSql (续1 ValueGeneratedOnAdd)-CSDN博客 小伙伴在使用 HasDefaultValueSql 时&#xff0c;对相关的 ValueGeneratedOnAdd, HasComputedColumnSql 也有了疑问&#xff1a; HasComputedColumnSql 对于计算…...

springboot整合h2

在 Spring Boot 中整合 H2 数据库非常简单。H2 是一个轻量级的嵌入式数据库&#xff0c;非常适合开发和测试环境。以下是整合 H2 数据库的步骤&#xff1a; 1. 添加依赖 首先&#xff0c;在你的 pom.xml 文件中添加 H2 数据库的依赖&#xff1a; <dependency><grou…...

Unity自带的真车模拟系统,速度不够大r时如何以匀速上桥

在 Unity 中&#xff0c;如果你使用自带的真车模拟系统&#xff08;如 Wheel Collider&#xff09;时&#xff0c;发现车辆上桥时速度不够&#xff0c;导致无法顺利上坡&#xff0c;可以通过以下方法调整车辆的行为&#xff0c;使其能够以匀速上桥&#xff1a; 1. 调整 Wheel C…...