Spring基础 SpringAOP

news2024/11/17 8:33:09

前言

我们都知道Spring中最经典的两个功能就是IOC和AOP

我们之前也谈过SpringIOC的思想 容器编程思想了

今天我们来谈谈SpringAOP的思想

首先AOP被称之为面向切面编程

实际上面向切面编程是面向对象的编程的补充和完善

重点就是对某一类问题的集中处理

前面我们写的统一异常管理和统一结果返回以及拦截器都是基于这个思想来创建的

我们发现这里的共性就是这些操作都有一个特点,他们都是统一操作的接口...

但是拦截器作用的是接口,AOP这类提供的操作的是方法

概念

切点(Printcut):这里的切点可以理解为切入的点,这里指的是一组规则,告诉程序对哪些方法来进行增强

连接点(Join Point):指的是满足上述切点规则的方法

通知(Advice): 对方法在前面/后面/周围加上一些处理(共性功能)

切面(Aspect): 切点 + 通知  (一类问题的解决方案)

SpringAOP

Spring 提供了一个通用的接口,可以帮助我们实现AOP的功能

比如对应用程序的监控,我们可以对每个接口之间加上计算实际运行时间

从计算的瓶颈解决问题

我们可以记录开始时间和节数时间然后作差,但是如果每个接口都一个一个写就没意思了

如果这里调用链非常长,我们还需要一个一个写,就太难受了呀

于是我们来使用AOP来解决问题

这里我们要先导入aop的依赖

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

这里虽然文件是Aspect包中的,但是却是Spring实现的

简单的实现

@Aspect
@Component
@Slf4j
public class TimeRecordAspect {
    @Around("execution(* com.example.bookmanager.controller.*.*(..))")
    public Object recordTime(ProceedingJoinPoint joinPoint) throws Throwable {

        //记录开始时间
        long startTime = System.currentTimeMillis();
        //目标方法
        Object proceed = joinPoint.proceed();
        //结束时间
        long endTime = System.currentTimeMillis();
        //打印日志
        log.info("方法执行时间"+(endTime-startTime)+"ms");
        return proceed;
    }
}

这样我们就可以在调用接口的时候打印其执行的时间了

以上的@Around注解表示就是环绕

在目标函数执行的前后都会执行

通知类型有如下几种

@Around: 环绕通知, 此注解标注的通知⽅法在⽬标⽅法前, 后都被执⾏
@Before: 前置通知, 此注解标注的通知⽅法在⽬标⽅法前被执⾏
@After: 后置通知, 此注解标注的通知⽅法在⽬标⽅法后被执⾏, ⽆论是否有异常都会执⾏
@AfterReturning: 返回后通知, 此注解标注的通知⽅法在⽬标⽅法后被执⾏, 有异常不会执⾏
@AfterThrowing: 异常后通知, 此注解标注的通知⽅法发⽣异常后执⾏
1.切点:这里的规则就是上面的Around里面的切点表达式
2.与切点表达式匹配的都是他描述的方法,也称之为连接点
3.通知 目标方法前后要做的操作
那么多包两层会怎么样呢????
比如先使用@Around再使用@Before和@After.....
这里就像一个栈一样,先进后出
注意:Around一定是要有返回值的,因为其有目标方法的执行
        Around的优先级高于其他

接口正常时

接口异常时

我们发现before和after在接口正常和异常的情况下都是会执行的

切点

注意需要一个空参方法
我们可以使用@Pointcut注解来代替大量重复的注解,后面的切点表达式就可以实现复用了
注意,如果切点是private的,在其他的类还是不能使用,声明为public并且使用全限定名即可
注:默认执行顺序为字典序,不可取,我们可以使用一个@Order来改变其优先级
数字越大优先级越低
下面我们来介绍一下切点表达式的内容
execution(* com.example.bookmanager.controller.*.*(..))
execution + 访问修饰符(可省略) + 返回类型 + 全类名 + 参数 + 异常(可省略)
这里的*表示任意单词可以替换返回类型,包名,类名方法等
         ..表示匹配多个任意符号
假设我们想对不同的类中的不同的方法来执行对应的连接
这个时候使用切点表达式就不能很好的完成问题了 我们就需要使用自定义注解对需要进行通知的方法进行修饰了

自定义注解

首先我们需要创建一个注解

我们需要声明他的作用域和生命周期

然后我们需要去做他的配置类/实现类

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface MyAspect {

}

我们暂时只实现一个Around功能

这里的@annotation就表示对什么注解生效

@Aspect
@Component
@Slf4j
public class MyAspectDemo {
    @Around("@annotation(com.example.springaop.config.MyAspect)")
    public Object doAround(ProceedingJoinPoint joinPoint) {
        log.info("do around before");
        Object o = null;
        try {
            o = joinPoint.proceed();
        } catch (Throwable e) {
            throw new RuntimeException(e);
        }
        log.info("do around after");
        return  o;
    }
}

后面我们可以用@MyAspect注解来修饰对应的方法

这样在调用的时候就可以实现其Around功能

SpringAOP的实现方式??

1.使用Aspect注解来实现

2.使用自定义注解来实现

3.基于XML文件使用api来实现  config:aop

4.基于代理来实现(比较久远)

代理模式(重点)

定义:

为其他对象提供⼀种代理以控制对这个对象的访问. 它的作⽤就是通过提供⼀个代理类, 让我们在调⽤⽬标⽅法的时候, 不再是直接对⽬标⽅法进⾏调⽤, ⽽是通过代理类间接调⽤.
代理前
代理后
生活中的代理也有很多
比如中介,经纪人,经销商,秘书........
主要角色:
Subject:业务接口类
RealSubject:业务实现类 具体的业务执行,也可以是被代理对象
Proxy:代理类,为RealSubject的代理
适用场景:
1.无法直接调用目标对象
2.目标对象给我们提供的功能不够,我们希望对目标对象已提供的方法进行功能增强
代理模式分为静态代理和动态代理
我们以生活中的中介来举例
静态代理就是我选好想看的房源之后,房源已经绑定了对应的中介了
动态代理就是我们选好想看的房源之后,平台自动分配中介
这种提前分配就称之为静态代理
运行时分配的就是动态代理

静态代理代码实现

接口
public interface Subject {
    void rentHouse();
}

房东

public class RealHouseSubject implements  Subject{

    @Override
    public void rentHouse() {
        System.out.println("我要卖房子");
    }
}

中介

public class HouseProxy implements  Subject{

    private RealHouseSubject target;

    public HouseProxy(RealHouseSubject target) {
        this.target = target;
    }

    @Override
    public void rentHouse() {
        System.out.println("开始代理");
        target.rentHouse();
        System.out.println("结束代理");
    }
}

类似于适配器模式,这里也是持有了第三方的房东授权

缺点是代码都写死了

动态代理实现

//JDK代理
public class JDKInvocationHandler implements InvocationHandler {
    private RealHouseSubject target;

    public JDKInvocationHandler(RealHouseSubject target) {
        this.target = target;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        System.out.println("开始代理");
        Object o = method.invoke(target, args);
        System.out.println("结束代理");
        return o;
    }
}

//main方法
        RealHouseSubject subject = new RealHouseSubject();
        Subject proxy= (Subject)Proxy.newProxyInstance(subject.getClass().getClassLoader(),
                new Class[]{Subject.class},new JDKInvocationHandler(subject));
        proxy.rentHouse();

这里有两种  CGLib和 JDK动态代理

这里就不做要求了

注意代理是基于反射实现的

主要记得这里的两个区别

JDK可以代理接口 不能代理类

CGLib可以代理接口也可以代理类

但是性能我不太确认,网上说两个性能谁高的都有,可能有硬件的影响  

博主可以后面测测看

注意Spring和SpringBoot在这里AOP的实现也是有差异的

代理工厂中有一个参数 proxyTargetClass  

默认Spring是false   默认实现接口使用JDK代理

SpringBoot从2.x之后设置为true     默认全部使用CGLib实现代理

proxyTargetClass⽬标对象代理⽅式
false实现了接⼝jdk代理
false未实现接⼝(只有实现类)cglib代理
true实现了接⼝cglib代理
true未实现接⼝(只有实现类)cglib代理

小总结

 AOP是⼀种思想,是对某⼀类事情的集中处理.Spring框架实现了AOP,称之为SpringAOP
2. SpringAOP常⻅实现⽅式有两种:

1.基于注解@Aspect来实现

2.基于⾃定义注解来实现,还有⼀些更原始的⽅式,⽐如基于代理,基于xml配置的⽅式,但⽬标⽐较少⻅
3. SpringAOP是基于动态代理实现的,有两种⽅式:

1.基本JDK动态代理实现

2.基于CGLIB动态代理
实现.运⾏时使⽤哪种⽅式与项⽬配置和代理的对象有关

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

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

相关文章

2024接口自动化测试入门基础知识【建议收藏】

接口自动化测试是指通过编写测试脚本和使用相关工具&#xff0c;对软件系统的接口进行自动化测试的过程。 今天本文从4个方面来介绍接口自动化测试入门基础知识 一、接口自动化测试是什么&#xff1f; 二、接口自动化测试流程&#xff1f; 三、接口自动化测试核心知识点有那些…

Linux--uboot移植(二)

修改uboot以匹配开发板的方式有两种&#xff0c;一种是在NXP原厂开发板i.MX 6ULL EVK的文件上进行修改&#xff0c;另一种仿造NXP的开发板文件&#xff0c;添加自己的开发板文件。 为了能更多的了解uboot&#xff0c;我们使用代码改动较大的第二种方式进行uboot的移植。 在修…

HTML5+JavaScript实现语音合成(文字转语音)

HTML5JavaScript实现语音合成&#xff08;文字转语音&#xff09; 本文介绍用HTML5和JavaScript实现语音合成朗读&#xff08;文字转语音&#xff09;。 Web Speech API 有两个部分&#xff1a;SpeechSynthesis 语音合成&#xff08;文本到语音 TTS&#xff09;和 SpeechReco…

双周回顾#009 - 大黄和我

双周回顾#009 - 大黄和我 说一个笑话&#xff0c;被朋友催更了&#xff0c;这就有点尴尬了&#xff01;&#xff01;&#xff01; 最近一个月&#xff0c;把空闲时间都点在了“玩”上&#xff0c;看闲书、玩游戏、背包客。 部落冲突 《埃隆马斯克传》一书中&#xff0c;马斯…

ubunt18.04安装ROS避坑指南

1 前言&#xff1a; 本文是ubunt18.04下安装ros的&#xff0c;如果想使用ros2,请看我的下一篇文章,ubunt18.04安装ROS2 本来是不该写的&#xff0c;有官方文档&#xff0c;还有很多大神的分析。但里面的坑太多&#xff0c;我考虑了一下&#xff0c;还是想记录下避免下次在跳泥…

day06 51单片机-点阵led

1 点阵LED 1.1 需求描述 本案例介绍如何使用点阵LED显示一排由左上到右下的斜线。 1.2 硬件设计 1.2.1 硬件原理图 点阵内部的原理图: 点阵LED的原理也非常简单,就是LED点灯。例如,我们想要让13列(阳极端)9行(阴极端)的LED点亮,需要13为高电平,9为低电平。注意对于…

《王者荣耀》游戏攻略:角色排行榜——墨子

作为天蝎座黄金圣斗士&#xff0c;墨子以他的正义感和荣誉感闻名&#xff0c;一直站在正义的一方&#xff0c;忠于女神雅典娜。他的猩红毒针象征着审判和死亡&#xff0c;而他所施加的十五针“安达里士”更是生命终结的预兆。在冥王再次发动战争之际&#xff0c;墨子追随雅典娜…

ResNet详解

一、认识ResNet ResNet&#xff08;Residual Network&#xff09;是一种深度神经网络结构&#xff0c;被广泛应用于图像分类、目标检测和语义分割等计算机视觉任务中。它是由微软亚洲研究院的何凯明等人于2015年提出的&#xff0c;通过引入残差连接&#xff08;residual conne…

javaScript3

javaScript 一.对象1.概念2.创建对象的三种方法(1).字面量创建&#xff08;利用{}&#xff09;(2)变量、属性、函数、方法的区别(3).new Object创建(4).构造函数 3.new关键字的执行过程4.遍历对象&#xff08;for..in) 二.内置对象 一.对象 1.概念 一组无序的相关属性和方法的…

Pycharm破解流程

1.下载pycharm 网上很多&#xff0c;随便找一个&#xff0c;懒得找的话&#xff0c;或者去我传上去的资源pycharm部分直接取 2.下载文件 文件部分&#xff0c;我放在pycharm文件里面一起 打开下载好的激活包 3.执行脚本 先执行unisntall-all-users.vbs,直接双击打开&#xff0c…

咱们来唠唠2024年参加三下乡社会实践活动怎样联系媒体投稿?

作为一名在校大学生,我深深珍视每一次增长见识、锻炼能力的机会,每年寒暑假期间,我都积极参与学院的“三下乡”社会实践活动。这不仅是我贴近生活、体验基层的大好时机,更是我积累人生经验、拓宽视野的重要途径。每次活动结束后,按照学院的要求,我们需要将实践纪实整理成文,向各…

《神奇女侠3:暗黑之魂》AI制作电影短片(下)

《神奇女侠3&#xff1a;暗黑之魂》AI制作电影短片&#xff08;下&#xff09; 黑暗滋生&#xff0c;世界沦陷&#xff0c;神奇女侠独战群魔&#xff0c;唤醒挚爱&#xff0c;守护最后的光明&#xff01; 《神奇女侠3&#xff1a;暗黑之魂》&#xff08;下&#xff09;故事继续…

Scikit-Learn支持向量机分类

Scikit-Learn 支持向量机分类 1、支持向量机&#xff08;SVM&#xff09;1.1、SVM概述1.2、SVM原理1.3、SVM的损失函数1.4、支持向量机分类的优缺点 2、Scikit-Learn支持向量机分类2.1、Scikit-Learn支持向量机分类API2.2、支持向量机分类初体验&#xff08;手写数字识别&#…

AES和RSA加解密算法学习笔记(实战版)

1. 写在前面 今天整理一篇有关密码学的学习笔记,原因是最近做的一个任务是在网络传输的时候,需要对传输的包进行加密和解密工作,以保证传输过程的安全性。所以,这个过程用到了AES和RSA两个算法。 场景:假设我要给我的老师传送毕设代码和论文, 我已经把代码和论文打成了一…

创新入门|解锁您的潜在市场:探秘付费点击广告(PPC)的秘密武器

在我们的营销领域&#xff0c;按点击付费 &#xff08;PPC&#xff09; 广告是增加流量、提高知名度并最终将点击转化为客户的基石策略。这种有针对性的广告模式&#xff0c;即企业只在点击广告时付费&#xff0c;彻底改变了公司投资在线推广的方式。尽管它看起来很简单&#x…

云打印怎么下单?网上云打印下单教程来了!

近些年来&#xff0c;随着移动互联网的发展&#xff0c;云打印也越来越火热。如今有越来越多的用户选择云打印服务。但是现在仍有很多不知道如何下单。那么云打印怎么下单呢&#xff1f;今天小易就来和大家介绍一下网上云打印的下单教程。 云打印怎么下单&#xff1f;网上云打印…

fastgpt、dify功能分析比较

目录 前言 一、dify、fastgpt是什么&#xff1f; 二、同场pk 1.大模型接入 2.chat&#xff08;最简应用&#xff09; 3.发布应用 4.知识库 5.workflow 6.其他 三、一些point记录 总结 前言 现在都开始AI应用开发&#xff0c;何谓AI应用&#xff0c;起码要和AI大模型…

CMake 编译项目

一、概述 cmake 是C一个很重要的编译和项目管理工具&#xff0c;我们在git 上以及常见的项目现在多数都是用cmake 管理的&#xff0c;那么我们今天就做一个同时有Opencv和CGAL 以及PCL 的项目。 二、项目管理 重点是CMakeList.txt 1、CMakeList.txt cmake_minimum_requir…

力扣HOT100 - 104. 二叉树的最大深度

解题思路&#xff1a; class Solution {public int maxDepth(TreeNode root) {if (root null) return 0;return Math.max(maxDepth(root.left), maxDepth(root.right)) 1;} }

构建云原生湖仓:Apache Iceberg与Amoro的结合实践

随着大数据技术的快速发展&#xff0c;企业对数据的处理和分析需求日益增长。传统的数据仓库已逐渐无法满足现代业务对数据多样性和实时性的要求&#xff0c;这促使了数据湖和数据仓库的融合&#xff0c;即湖仓一体架构的诞生。在云原生技术的推动下&#xff0c;构建云原生湖仓…