SpringAOP学习文档

news2024/11/25 4:51:25

目录

  • 一、概念
  • 二、示例代码
  • 三、切点
    • 1、execution
    • 2、within
    • 3、this
    • 4、target
    • 5、args
    • 6、@annotation
    • 7、@within
    • 8、@target
    • 9、@args
    • 10、组合切点表达式
    • 11、在@Before注解中使用自定义的切入点表达式,以及切入点方法
    • 12、获取指定类型的真实对象
  • 四、通知
    • 1、@Around注解的通知方法中调用proceed()方法之前的代码
    • 2、@Before
    • 3、连接点方法
    • 4、@AfterReturning
    • 5、@AfterThrowing
    • 6、@After
    • 7、@Around注解的通知方法中调用proceed()方法之后的代码
  • 五、注解使用说明
  • 六、参考资料

一、概念

关键名词:

  • 目标对象:需要被增强的对象
  • 连接点:需要被增强的方法
  • 切面:添加@Aspect的类,一个类里面可以有多个切点和多个通知
  • 切点:可以针对注解或者类路径进行查找
  • 通知:在切点上执行增强逻辑
  • 路径表达式:匹配连接点的表达式
  • 织入:将切面和目标对象连接起来

画图表示:

在这里插入图片描述

代码表示:

在这里插入图片描述

二、示例代码

情况说明:

在下面目录中的代码片段并不完整,缺失的内容请下载示例代码查看~

百度网盘:

链接:https://pan.baidu.com/s/1onHsCNHWIdfjmAUTg7q8TA?pwd=gyg1

提取码:gyg1

启动说明:

执行主启动类的main方法即可

在这里插入图片描述

启动日志:

spring启动完成,尝试调用TestController类的test方法……
===测试args,目标类名称:TestController、连接点(方法)名称:test
===测试within,目标类名称:TestController、连接点(方法)名称:test
+++测试@Around注解,针对目标类TestServiceImpl的方法test,在执行joinPoint.proceed()方法之前……
+++测试@Before注解,在目标类TestServiceImpl的方法test之前执行……
===测试@annotation,目标类名称:TestServiceImpl、连接点(方法)名称:test
===测试@args,目标类名称:TestServiceImpl、连接点(方法)名称:test
===测试@within,目标类名称:TestServiceImpl、连接点(方法)名称:test
===测试组合切点表达式,目标类名称:TestServiceImpl、连接点(方法)名称:test
===测试execution,目标类名称:TestServiceImpl、连接点(方法)名称:test
===测试直接获取相应对象,目标类名称:TestServiceImpl、连接点(方法)名称:test、类注解值:实现类、方法注解值:方法、方法参数名称:TestEntity、方法参数对应类注解值:实体类
===测试借助切点方法获取相应对象,目标类名称:TestServiceImpl、连接点(方法)名称:test、类注解值:实现类、方法注解值:方法、方法参数名称:TestEntity、方法参数对应类注解值:实体类
===测试通知中使用组合切入点方法,目标类名称:TestServiceImpl、连接点(方法)名称:test
===测试通知中使用组合自定义的切入点表达式,目标类名称:TestServiceImpl、连接点(方法)名称:test
===测试通知中使用组合 自定义的切入点表达式 + 切入点方法,目标类名称:TestServiceImpl、连接点(方法)名称:test
===测试target,目标类名称:TestServiceImpl、连接点(方法)名称:test
===测试this,目标类名称:TestServiceImpl、连接点(方法)名称:test
》》》执行测试方法……
+++测试@AfterReturning注解,在目标类TestServiceImpl的方法test执行正常返回时,方法执行结果:成功
+++测试@After注解,针对目标类TestServiceImpl的方法test,无论是否发生异常,一定会执行……
+++测试@Around注解,针对目标类TestServiceImpl的方法test,在执行joinPoint.proceed()方法之后……

三、切点

注意内容:

/**
 * 通配符说明:
 * .:包和包、包和方法之前的普通连接符号
 * ..:如果用在路径上,代表中间可有有多个任意路径(中间用.分隔的多个路径);如果用在方法参数上,代表不限制参数列表
 * *:指代任意单个单词,可以用在路径(包名、类名、方法名)、修饰符、返回值类型
 * +:匹配任何继承自指定的类,例如:execution(* com.example.Parent+.*(..)):匹配com.example.Parent类及其子类的任何方法。
 */

/**
 * 注意事项:
 * 1、如果在通知方法中使用JoinPoint类型参数,那就一定要放在第1个,否则会导致tomcat启动过程中出现空指针异常,从而启动失败;当然可以选择不放
 */

1、execution

// 测试:execution
// 用途:指定到方法级别
// 通配符:允许使用
// 格式:execution(修饰符 返回值类型 方法路径(参数类型列表))
// 注意:修饰符可以省略,省略代表不限制修饰符
//    @Pointcut("execution(public String com.atguigu.test.controller.TestController.test(..))") // 指定修饰符、返回值类型、方法全路径、任意参数类型
//    @Pointcut("execution(* com.atguigu.test.controller.TestController.test(..))") // 任意修饰符、任意返回值类型、方法全路径、任意参数类型
@Pointcut("execution(* com.atguigu.*.service..test(..))") // 任意修饰符、任意返回值类型、指定包下的所有方法
public void executionPointcut() {}

@Before("executionPointcut()")
public void executionAdvice(JoinPoint joinPoint) {
    String className = joinPoint.getTarget().getClass().getSimpleName();
    String methodName = joinPoint.getSignature().getName();
    System.out.printf("===测试execution,目标类名称:%s、连接点(方法)名称:%s\n",  className, methodName);
}

2、within

// 测试:within
// 用途:指定到类级别
// 通配符:允许使用
// 格式:within(类路径)
@Pointcut("within(com.atguigu.test.controller.TestController)") // 具体类
//    @Pointcut("within(com.atguigu.test.service.impl.*)") // 包中所有类
//    @Pointcut("within(com..test..*)") // 子包中所有类(包名称以com开头,中间包含test即可)
public void withinPointcut() {}

@Before("withinPointcut()")
public void withinAdvice(JoinPoint joinPoint) {
    String className = joinPoint.getTarget().getClass().getSimpleName();
    String methodName = joinPoint.getSignature().getName();
    System.out.printf("===测试within,目标类名称:%s、连接点(方法)名称:%s\n",  className, methodName);
}

3、this

// 测试:this
// 用途:指定接口,捕获接口实现类中方法被调用的情况
// 通配符:禁止使用
// 格式:this(接口路径)
// 注意:接口路径不允许使用通配符类型模式,必须使用类型名称
@Pointcut("this(com.atguigu.test.service.TestService)")
public void thisPointcut() {}

@Before("thisPointcut()")
public void thisAdvice(JoinPoint joinPoint) {
    String className = joinPoint.getTarget().getClass().getSimpleName();
    String methodName = joinPoint.getSignature().getName();
    System.out.printf("===测试this,目标类名称:%s、连接点(方法)名称:%s\n",  className, methodName);
}

4、target

// 测试:target
// 用途:指定接口,捕获接口实现类中方法被调用的情况
// 通配符:禁止使用
// 格式:target(接口路径)
// 注意:接口路径不允许使用通配符类型模式,必须使用类型名称
@Pointcut("this(com.atguigu.test.service.TestService)")
public void targetPointcut() {}

@Before("targetPointcut()")
public void targetAdvice(JoinPoint joinPoint) {
    String className = joinPoint.getTarget().getClass().getSimpleName();
    String methodName = joinPoint.getSignature().getName();
    System.out.printf("===测试target,目标类名称:%s、连接点(方法)名称:%s\n",  className, methodName);
}

5、args

// 测试:args
// 用途:指定参数类型
// 格式:args(参数类型列表)
@Pointcut("within(com.atguigu.test.controller.TestController) && args(String)")
public void argsPointcut() {}

@Before("argsPointcut()")
public void argsAdvice(JoinPoint joinPoint) {
    String className = joinPoint.getTarget().getClass().getSimpleName();
    String methodName = joinPoint.getSignature().getName();
    System.out.printf("===测试args,目标类名称:%s、连接点(方法)名称:%s\n",  className, methodName);
}

6、@annotation

// 测试:@annotation
// 用途:指定方法上的注解,添加该注解的方法都是连接点方法
// 通配符:禁止使用
// 格式:@annotation(注解路径)
// 注意:注解路径不允许使用通配符类型模式,必须使用类型名称
@Pointcut("@annotation(com.atguigu.test.annotation.TestAnnotation)")
public void atAnnotationPointcut() {}

@Before("atAnnotationPointcut()")
public void atAnnotationAdvice(JoinPoint joinPoint) {
    String className = joinPoint.getTarget().getClass().getSimpleName();
    String methodName = joinPoint.getSignature().getName();
    System.out.printf("===测试@annotation,目标类名称:%s、连接点(方法)名称:%s\n",  className, methodName);
}

7、@within

// 测试:@within
// 用途:指定类上的注解,添加该注解的类中所有方法都是连接点方法
// 通配符:禁止使用
// 格式:@within(注解路径)
// 注意:注解路径不允许使用通配符类型模式,必须使用类型名称
@Pointcut("@within(com.atguigu.test.annotation.TestAnnotation)")
public void atWithinPointcut() {}

@Before("atWithinPointcut()")
public void atWithinAdvice(JoinPoint joinPoint) {
    String className = joinPoint.getTarget().getClass().getSimpleName();
    String methodName = joinPoint.getSignature().getName();
    System.out.printf("===测试@within,目标类名称:%s、连接点(方法)名称:%s\n",  className, methodName);
}

8、@target

// 测试:@target
// 警告:没搞懂怎么用,暂时放弃了

9、@args

// 测试:@args
// 用途:指定参数所属类上的注解,从而确定连接点方法
// 格式:@args(参数类型添加的注解路径)
@Pointcut("within(com.atguigu.test.service..*) && @args(com.atguigu.test.annotation.TestAnnotation, ..)")
public void atArgsPointcut() {}

@Before("atArgsPointcut()")
public void atArgsAdvice(JoinPoint joinPoint) {
    String className = joinPoint.getTarget().getClass().getSimpleName();
    String methodName = joinPoint.getSignature().getName();
    System.out.printf("===测试@args,目标类名称:%s、连接点(方法)名称:%s\n",  className, methodName);
}

10、组合切点表达式

// 测试:组合切点(Pointcut)表达式
// 格式:支持通过 &&、||、! 来组合 pointcut 表达式
@Pointcut("executionPointcut() || atAnnotationPointcut() || atWithinPointcut()")
public void combinationPointcut() {}

@Before("combinationPointcut()")
public void combinationAdvice(JoinPoint joinPoint) {
    String className = joinPoint.getTarget().getClass().getSimpleName();
    String methodName = joinPoint.getSignature().getName();
    System.out.printf("===测试组合切点表达式,目标类名称:%s、连接点(方法)名称:%s\n",  className, methodName);
}

11、在@Before注解中使用自定义的切入点表达式,以及切入点方法

// 说明:在@Before注解中使用切入点方法
@Before("executionPointcut() || atAnnotationPointcut() || atWithinPointcut()")
public void mix1PointcutAdvice(JoinPoint joinPoint) {
    String className = joinPoint.getTarget().getClass().getSimpleName();
    String methodName = joinPoint.getSignature().getName();
    System.out.printf("===测试通知中使用组合切入点方法,目标类名称:%s、连接点(方法)名称:%s\n",  className, methodName);
}


// 说明:在@Before注解中使用自定义的切入点表达式
@Before("execution(* com.atguigu.*.service..test(..)) || @annotation(com.atguigu.test.annotation.TestAnnotation)")
public void mix2PointcutAdvice(JoinPoint joinPoint) {
    String className = joinPoint.getTarget().getClass().getSimpleName();
    String methodName = joinPoint.getSignature().getName();
    System.out.printf("===测试通知中使用组合自定义的切入点表达式,目标类名称:%s、连接点(方法)名称:%s\n",  className, methodName);
}


// 说明:在@Before注解中使用自定义的切入点表达式 + 切入点方法
@Before("execution(* com.atguigu.*.service..test(..)) || atAnnotationPointcut() || atWithinPointcut()")
public void mix3PointcutAdvice(JoinPoint joinPoint) {
    String className = joinPoint.getTarget().getClass().getSimpleName();
    String methodName = joinPoint.getSignature().getName();
    System.out.printf("===测试通知中使用组合 自定义的切入点表达式 + 切入点方法,目标类名称:%s、连接点(方法)名称:%s\n",  className, methodName);
}

12、获取指定类型的真实对象

@Before(value = "getObjPointcut(classAnnotation, methodAnnotation, entity, entityAnnotation)")
public void getObjAdvice(JoinPoint joinPoint, TestAnnotation classAnnotation, TestAnnotation methodAnnotation, TestEntity entity, TestAnnotation entityAnnotation) {
    String className = joinPoint.getTarget().getClass().getSimpleName();
    String methodName = joinPoint.getSignature().getName();
    System.out.printf("===测试借助切点方法获取相应对象,目标类名称:%s、连接点(方法)名称:%s、类注解值:%s、方法注解值:%s、方法参数名称:%s、方法参数对应类注解值:%s\n",  className, methodName, classAnnotation.value(), methodAnnotation.value(), entity.getClass().getSimpleName(), entityAnnotation.value());
}

@Before(value = "@within(classAnnotation) && @annotation(methodAnnotation) && args(entity, ..) && @args(entityAnnotation, ..)")
public void getObj2Advice(JoinPoint joinPoint, TestAnnotation classAnnotation, TestAnnotation methodAnnotation, TestEntity entity, TestAnnotation entityAnnotation) {
    String className = joinPoint.getTarget().getClass().getSimpleName();
    String methodName = joinPoint.getSignature().getName();
    System.out.printf("===测试直接获取相应对象,目标类名称:%s、连接点(方法)名称:%s、类注解值:%s、方法注解值:%s、方法参数名称:%s、方法参数对应类注解值:%s\n",  className, methodName, classAnnotation.value(), methodAnnotation.value(), entity.getClass().getSimpleName(), entityAnnotation.value());
}

四、通知

注意内容:

/**
 * 通配符说明:
 * .:包和包、包和方法之前的普通连接符号
 * ..:如果用在路径上,代表中间可有有多个任意路径(中间用.分隔的多个路径);如果用在方法参数上,代表不限制参数列表
 * *:指代任意单个单词,可以用在路径(包名、类名、方法名)、修饰符、返回值类型
 * +:匹配任何继承自指定的类,例如:execution(* com.example.Parent+.*(..)):匹配com.example.Parent类及其子类的任何方法。
 */

/**
 * 注意事项:
 * 1、如果在通知方法中使用JoinPoint类型参数,那就一定要放在第1个,否则会导致tomcat启动过程中出现空指针异常,从而启动失败;当然可以选择不放
 * 2、每一种类型的通知都列出了1个,其实针对同一个切点方法,也可以添加多次同类型通知,这些通知都会执行
 * 3、始终使用符合你要求的最不强大的 advice 形式。例如,如果 before advice 足以满足你的需要,就不要使用 around advice。
 * 4、执行“连接点方法”和“通知方法”都不报错,执行通知的顺序:
 *    @Around注解方法中调用proceed()方法之前
 *    @Before
 *    连接点方法
 *    @AfterReturning
 *    @After
 *    @Around注解方法中调用proceed()方法之后
 * 5、执行“连接点方法”报错,但是执行“通知方法”不报错,执行通知的顺序:
 *    @Around注解方法中调用proceed()方法之前
 *    @Before
 *    连接点方法(报错),往上抛出异常
 *    @AfterThrowing
 *    @After
 *    @Around注解方法,往上抛出异常
 * 6、执行“连接点方法”不报错,但是执行“通知方法”报错,执行通知的顺序:
 *    任意一个通知方法出现异常,将会直接抛出异常,并且不会执行后面的所有通知方法
 */

切点:

// 切点
@Pointcut("execution(* com.atguigu.*.service..test(..))") // 任意修饰符、任意返回值类型、指定包下的所有方法
public void pointcut() {}

1、@Around注解的通知方法中调用proceed()方法之前的代码

// Around通知:在方法运行之前和之后进行工作,并决定何时、如何、甚至是否真正运行该方法
// 说明:1、该方法的第一个参数必须是 ProceedingJoinPoint 类型,从而调用proceed()以执行连接点方法。
//      2、如果不为proceed()方法传递参数,那么该方法底层在调用连接点方法时将会传原始参数给它;
//        如果调用重载的 proceed() 方法,它接受一个参数数组(Object[]),那么该方法底层在调用连接点方法时将使用参数数组(Object[])。
//      3、如果你将 around advice 方法的返回类型声明为 void,那么将总是返回给调用者 null,有效地忽略了任何调用 proceed() 的结果。
//         因此,我们建议 around advice 方法声明一个 Object 的返回类型。该advice方法通常应该返回调用 proceed() 所返回的值,
//         即使底层方法的返回类型为 void。然而,advice可以根据使用情况选择性地返回一个缓存的值、一个封装的值或一些其他的值。
@Around("pointcut()")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
    // 测试下面算术异常的影响,将导致所有通知方法都不会执行
//        int a = 10 / 0;
    String className = joinPoint.getTarget().getClass().getSimpleName();
    String methodName = joinPoint.getSignature().getName();
    System.out.printf("+++测试@Around注解,针对目标类%s的方法%s,在执行joinPoint.proceed()方法之前……\n",  className, methodName);

2、@Before

// Before通知:在切点匹配的方法执行之前
@Before("pointcut()")
public void before(JoinPoint joinPoint) {
    // JoinPoint对象方法:https://eclipse.dev/aspectj/doc/released/runtime-api/org/aspectj/lang/JoinPoint.html
    String className = joinPoint.getTarget().getClass().getSimpleName();
    String methodName = joinPoint.getSignature().getName();
    System.out.printf("+++测试@Before注解,在目标类%s的方法%s之前执行……\n",  className, methodName);
}

3、连接点方法

// Around通知:在方法运行之前和之后进行工作,并决定何时、如何、甚至是否真正运行该方法
@Around("pointcut()")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
    ………………
    Object returnValue = joinPoint.proceed();

4、@AfterReturning

// AfterThrowing通知:当切点匹配的方法执行出现异常时
// 说明:1、可以通过异常类型来匹配通知方法,比如我们这里只处理空指针异常(如果不需要指定特殊异常类型,可以使用 Throwable 作为异常类型)
//      2、只接收来自连接点(用户声明的目标方法)本身的异常,而不是来自其他通知方法,比如:添加注解 @After/@AfterReturning 方法的情况
//      3、当一个连接点方法的执行抛出异常退出时,该异常将作为相应的参数值传递给对应处理异常的通知方法
@AfterThrowing(value = "pointcut()", throwing = "ex")
public void executionAdvice(JoinPoint joinPoint, NullPointerException ex) {
    String className = joinPoint.getTarget().getClass().getSimpleName();
    String methodName = joinPoint.getSignature().getName();
    System.out.printf("+++测试@AfterThrowing注解,在目标类%s的方法%s出现空指针异常时执行,异常信息:%s\n", className, methodName, ex.getMessage());
}

5、@AfterThrowing

// AfterThrowing通知:当切点匹配的方法执行出现异常时执行
// 说明:1、可以通过异常类型来匹配通知方法,比如我们这里只处理算术异常(如果不需要指定特殊异常类型,可以使用 Throwable 作为异常类型)
//      2、只接收来自连接点(用户声明的目标方法)本身的异常,,而不是来自附带的 @After / @AfterReturning 方法。
//      3、当一个连接点方法的执行抛出异常退出时,该异常将作为相应的参数值传递给对应处理异常的通知方法
@AfterThrowing(value = "pointcut()", throwing = "ex")
public void executionAdvice(JoinPoint joinPoint, ArithmeticException ex) {
    String className = joinPoint.getTarget().getClass().getSimpleName();
    String methodName = joinPoint.getSignature().getName();
    System.out.printf("+++测试@AfterThrowing注解,在目标类%s的方法%s出现算术异常时执行,异常信息:%s\n", className, methodName, ex.getMessage());
}

6、@After

// After通知:当一个匹配的方法执行退出时,一定会执行该通知
// 将对任何结果、正常返回或从连接点(用户声明的目标方法)抛出的异常进行调用,通常被用于释放资源和类似的目的。
// 类似于try-catch语句中的finally块,这与 @AfterReturning 不同,后者只适用于成功的正常返回。
@After("pointcut()")
public void after(JoinPoint joinPoint) {
    String className = joinPoint.getTarget().getClass().getSimpleName();
    String methodName = joinPoint.getSignature().getName();
    System.out.printf("+++测试@After注解,针对目标类%s的方法%s,无论是否发生异常,一定会执行……\n",  className, methodName);
}

7、@Around注解的通知方法中调用proceed()方法之后的代码

// Around通知:在方法运行之前和之后进行工作,并决定何时、如何、甚至是否真正运行该方法
@Around("pointcut()")
public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
    ………………
    // 测试@After通知在执行joinPoint.proceed()方法中执行,而不会受到下面算术异常的影响
//        int a = 10 / 0;
    System.out.printf("+++测试@Around注解,针对目标类%s的方法%s,在执行joinPoint.proceed()方法之后……\n",  className, methodName);
    return returnValue;
}

五、注解使用说明

在这里插入图片描述

六、参考资料

  • spring中文官网

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2212253.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

AI赋能,精准防控:AI智能分析网关V4人员徘徊算法的技术优势与应用场景

随着科技的飞速发展,视频监控系统在各个领域的应用越来越广泛,从公共安全到商业管理,再到交通监控等。AI智能分析网关V4作为新一代的视频分析设备,以其强大的智能分析能力和多样化的应用场景,成为市场关注的焦点。本文…

pytorch与卷积神经网络实战笔记

课程视频链接 CNN卷积神经网络算法原理 全神经网络的整体结构 输入层(x1, x2, x3…)->隐藏层(全连接)->输出层,整体就类似于一个函数,输入x,经过函数module(x)得到输出y的过程&#xf…

WPF常见容器全方位介绍

Windows Presentation Foundation (WPF) 是微软的一种用于构建Windows桌面应用程序的UI框架。WPF的布局系统基于容器,帮助开发者以灵活、响应的方式组织用户界面 (UI) 元素。本篇文章将详细介绍WPF中几种常见的容器,包括Grid、StackPanel、WrapPanel、Do…

SpringMVC源码-处理器适配器HandlerAdapter

因为定义controller的方式有三种,每种不同的方式调用的方法不同,尤其是注解修饰的 方法名是自定义的 因此需要通过适配器模式来调用方法执行 initStrategies进行适配器的初始化 处理器适配器一共有如下四种: org.springframework.web.servlet.Handl…

springboot系列--web相关知识探索五

一、前言 web相关知识探索四中研究了请求中所带的参数是如何映射到接口参数中的,也即请求参数如何与接口参数绑定。主要有四种、分别是注解方式、Servlet API方式、复杂参数、以及自定义对象参数。web相关知识探索四中主要研究了复杂参数底层绑定原理。本次主要是研…

有效三⻆形的个数 05

有效三⻆形的个数 我写的 class Solution {public int triangleNumber(int[] nums) {Arrays.sort(nums);int sum0;for (int knums.length-1;k>1;k--) {int left0;int rightk-1;while(right>left) {if (nums[left]nums[right]>nums[k]) {sum(right-left);right--;…

QD1-P26、27、28 CSS 属性 文本

本节(P26、27、28 三合一)学习:CSS 文本属性。 ‍ 本节视频 https://www.bilibili.com/video/BV1n64y1U7oj?p26 CSS(层叠样式表)中用于设置文本样式的属性有很多,以下是一些常用的文本属性: …

[数据结构]栈的实现与应用

文章目录 一、引言二、栈的基本概念1、栈是什么2、栈的实现方式对比3、函数栈帧 三、栈的实现1、结构体定义2、初始化3、销毁4、显示5、数据操作 四、分析栈1、优点2、缺点 五、总结1、练习题2、源代码 一、引言 栈,作为一种基础且重要的数据结构,在计算…

Mybatis高级查询-一对多查询

表介绍和表关系说明 新建以下4张表 tb_user:用户表 tb_order:订单表 tb_item:商品表 tb_orderdetail:订单详情表 【表关系】 1.tb_user和 tb_order表关系tb_user 《》 tb_order:一对多, 一个人可以下多…

Oracle漏洞修复 19.3 补丁包 升级为19.22

1.场景描述 上周末2024-10-12日,服务器扫出漏洞,希望及时修复。其中,oracle的漏洞清单如下,总结了下,基本都是 Oracle Database Server 的 19.3 版本到 19.20 版本和 21.3 版本到 21.11 版本存在安全漏洞,即版本问题。如: Oracle Database Server 安全漏洞(CVE-2023-22…

241013深度学习之GoogleLeNet

文章目录 1. GoogleLeNet2.Inception块3.googleLeNet模型4.训练模型4.1运行结果图 5.小结 1. GoogleLeNet 全称:含并行连接的网络 在2014年的ImageNet图像识别挑战赛中,一个名叫GoogLeNet (Szegedy et al., 2015)的网络架构大放异彩。 GoogLeNet吸收了N…

ZED相机的使用

ZED双目相机型号是ZED 2 立体相机(ZED2 Stereo Camera,Stereolabs , San Francisco, USA),其中还包括USB 3.0 数据线,以及一个迷你三脚架。 一、查看自己的cuda nvidia-smi # 查看显卡驱动信息 nvcc -V # 查看CUDA的…

C++——vector的了解与使用

目录 引言 vector容器的基本概念 1.功能 2.动态大小 3.动态扩展 vector的接口 1.vector的迭代器 2.vector的初始化与销毁 3.vector的容量操作 3.1 有效长度和容量大小 (1)使用示例 (2)扩容机制 3.2 有效长度和容量操作 (1)reserve (2)resize 4.vector的访问操作…

电脑基础知识:mfc110.dll丢失的解决方法

1.mfc110.dll 丢失常见原因 mfc110.dll 文件的丢失或损坏是Windows系统中常见的问题,它可能由多种原因引起,以下是一些主要的因素: 不完全的软件卸载 在卸载程序时,如果相关的 DLL 文件没有被正确移除,可能会导致文件…

aarch64-linux-gnu-gcc交叉编译opencv移植到linuxaarch64上

所谓的将OpenCV移植到某个平台,就是用该平台对应的编译器将OpenCV源代码编译成so库 1.下载3.4.5opencv源码 解压 安装aarch64-linux-gnu-gcc 在执行 bash build-linux_RK3588.sh过程中,提示什么,装就行了。 装完之后 trolongtrolong-virtu…

机器学习的四大学派:符号主义学派、贝叶斯学派、连接主义学派与进化仿生学派

目录 前言1. 符号主义学派1.1 含义与理论基础1.2 特点1.3 应用 2. 贝叶斯学派2.1 含义与理论基础2.2 特点2.3 应用 3. 连接主义学派3.1 含义与理论基础3.2 特点3.3 应用 4. 进化仿生学派4.1 含义与理论基础4.2 特点4.3 应用 结语 前言 机器学习作为人工智能的核心技术之一&…

【AUTOSAR 基础软件】ComM模块详解(通信管理)

文章包含了AUTOSAR基础软件(BSW)中ComM模块相关的内容详解。本文从AUTOSAR规范解析,ISOLAR-AB配置以及模块相关代码分析三个维度来帮读者清晰的认识和了解ComM这一基础软件模块。文中涉及的ISOLAR-AB配置以及模块相关代码都是依托于ETAS提供的…

2.随机变量及其分布

第二章 随机变量及其分布 1. 随机变量及其分布 1.1 随机变量的定义 定义1.1 随机变量 ​ 定义在样本空间 Ω \Omega Ω上的实值函数 X X ( ω ) XX(\omega) XX(ω)称为随机变量,常用大写字母 X , Y , Z X,Y,Z X,Y,Z等表示随机变量,其取值用小写字母 x , y , z …

手写mybatis之返回Insert操作自增索引值

前言 技术的把控,往往都是体现在细节上! 如果说能用行,复制粘贴就能完成需求,出错了就手忙脚乱。那你一定不是一个高级开发,对很多的技术细节也都不了解。 目标 在前面所有的章节内容对 ORM 框架的实现中,其…

VMware16虚拟机安装macOS Monterey 12详细教程

1、虚拟机配置安装 安装WMware Workstation 16,打开安包装包,只需点下一步即可,安装过程略。 安装完毕后,检查任务管理器,如果有VMware程序运行,就结束任务。 打开【运行】,快捷键win+R,输入services.msc 找到所有VMware开头的服务 将这些VMware服务逐一停用。 鼠标…