SpringAOP简介及实现(包含切面、切点、连接点和通知)

目录

1.什么是AOP、SpringAOP?

2.AOP的组成

3.SpringAOP的实现

4.切点的表达式


1.什么是AOP、SpringAOP?

在学习SpringAOP之前,我们得先了解一下什么是AOP。AOP是一种面向切面编程的思想。那什么是切面呢?它其实是对某一类事情的集中处理。比如,使用AOP的具体实现用来统一处理用户在访问网页时检查用户的登录状态的判断。在之前的学习中,我们是通过在每个需要处理用户请求的方法中都编写用户登录状态判断的代码,好在整体的方法数还比较少。


那如果方法很多呢?我们就需要在每一个每一个方法中编写相同逻辑代码判断用户的状态,我们写了如此多重复的代码反而是为了处理相同的一段逻辑,这是项目开发中的大忌,大大增强了我们程序的耦合性。而这一问题就可以使用AOP思想来进行处理,当用户发送请求时,我们将处理用户请求的不同方法中判断用户是否登录的逻辑视为一类事情,使用AOP思想的具体实现对这一类事情进行集中处理,这样我们只需要编写一遍代码,便能够在需要任何进行用户是否登录的逻辑判断的方法中进行判断与处理。上述的这种做法就是AOP思想的一种具体实现。

 


除此之外,使用SpringAOP还能够帮助我们进行:

  1. 统一日志记录
  2. 统一方法运行时间统计
  3. 统一的返回个事处理
  4. 统一的异常处理
  5. 事务的开启和提交
  6. ...

说了这么多,AOP和SpringAOP具体有什么联系呢?

不知道大家是否还记得,我们在Spring学习之初知道:IOC是一种控制反转思想,而DI就是这种思想的具体实现。类似的,AOP就是一种面向切面的思想或者说是集中处理的思想,而SpringAOP就是就针对这种切面思想的具体实现。既然SpringAOP的功能这么强大,那还不赶紧来学习一下它的使用和实现原理!

2.AOP的组成

在正式开始学习SpringAOP之前,我们有必要对AOP的组成进行理解,以便对我们接下来SpringAOP的具体实现和原理能有个充分的理解。AOP的组成大体共有以下四部分:

  1. 切面(Aspect)
    是切点和通知的结合,包括了横切逻辑的定义,也包括了逻辑点的定义。
  2. 切点(Pointcut)
    用来匹配连接点。
  3. 通知(Advice)
    切点的实现逻辑
  4. 连接点(Join Point)
    应用执行过程中能够插入切面的一个点

wc,看完懵逼,这是什么?看完定义想必肯定一头雾水。接下来,我们试着用通俗易懂的语言来描述一下AOP的这几个组成部分:

  1. 首先:切面
    在程序中,切面说白了其实就是一个类,这个类中包含了具体的拦截规则和拦截后的业务实现,是切点和通知的集合。
  2. 其次:切点。
    就是上面切面类中主动拦截时的条件。
  3. 然后:通知
    就是在拦截成功后,针对这一拦截做具体处理的业务代码。在AOP,通知又分为以下五类:
    1. 前置通知:在执行目标业务方法之前执行的方法
    2. 后置通知:在执行目标业务方法之后执行的方法
    3. 环绕通知:在执行目标业务方法之前和之后执行的方法
    4. 异常通知:目标方法抛出异常后执行的方法
    5. 返回通知:目标方法返回之后或者说执行结束后执行的方法
  4. 最后:连接点
    指的就是所有可能触发切面类中拦截规则即切点的所有请求的集合。

看完之后如果还不是特别清楚的话,我们接下来就来具体实现一个SpringAOP程序,来更好的理解上述AOP的相关组成。

3.SpringAOP的实现

接下来我们以拦截UserController类中的所有方法为例,来学习一下SpringAOP的具体实现步骤。


SpringAOP的具体实现分为以下三个步骤:

  1. 添加SpringAOP框架支持
  2. 定义切面类和切点
  3. 定义通知方法

SpringAOP中相关组成使用注解速查:

定义切面类@Aspect
定义切点@PointCut("切点表达式")
定义通知方法-前置通知@Before("针对切点的方法名")
定义通知方法-后置通知@After("针对切点的方法名")
定义通知方法-环绕通知@Around("针对切点的方法名")
定义通知方法-异常通知@AfterThrowing("针对切点的方法名")
定义通知方法-返回通知@AfterReturning("针对切点的方法名")

我们来在程序中具体实现,同时学习一下SPringAOP实现的细节及注意事项:

 

4.切点的表达式

AspectJ ⽀持三种通配符
* :匹配任意字符,只匹配⼀个元素(包,类,或⽅法,⽅法参数)
.. :匹配任意字符,可以匹配多个元素 ,在表示类时,必须和 * 联合使⽤。
+ :表示按照类型匹配指定类的所有类,必须跟在类名后⾯,如 com.cad.Car+ ,表示继承该类的 所有⼦类包括本身

切点表达式由切点函数组成,其中execution()为最常用的切点函数,切点定义的注解及其函数的语法如下:

@PointCut("execution(<修饰符> <返回类型> <包.类.方法(参数)> <异常>)")

【ps】:其中的修饰符和异常选项通常省略


😄例如,在我们上边的SpringAOP程序中:


 接下里我们来看看切点表达式中对应选项的一些常用写法:

😄对于修饰符

修饰符含义
*匹配目标类中被任意修饰符修饰的方法
public匹配目标类中被public修饰的方法
......

😄对于返回类型

返回类型含义
*匹配目标类中任意返回值类型的方法
String匹配目标类中字符串类型返回值的方法
void匹配目标类中无返回值的方法
......

😄对于包类型

包类型含义
com.shuai.demo固定包demo
com.shuai.demo.*.servicedemo二级包中任意的service包,例如:(com.shuai.demo.staff.service)
com.shuai.demo..demo包下的任意子包,包含自身
com.shuai.demo.*.service..demo二级包中任意的service包中的任意包,包含service自身
......

😄对于包中的类

类写法含义
包.UserController固定类Controller
包.*Controller以Controller结尾的类
包.User*以User开头的类
包.*包中的任意类
.....

😄 对于类中的方法

方法的写法含义
包.类.getUser固定方法getUser()
包.类.get*类中以add开头的方法
包.类.*Do类中以Do结尾的方法
包.类.*类中的任意方法
......

😄对于方法中的参数

方法中的参数写法含义
包.类.方法()类中的无参方法
包.类.方法(int)类中带一个Int类型参数的方法
包.类.方法(int,String)类中带一个int类型一个String类型的参数的方法
包.类.方法(..)类中任意参数的方法
......
 

写一些切点表达式来理解一下它的含义:

  • execution(* com.shuai.demo.User.*(..)) :匹配 User 类⾥的所有⽅法。
  • execution(* com.shuai.demo.User+.*(..)) :匹配User类的⼦类包括User类中的所有⽅法。
  • execution(* com.shuai.*.*(..)) :匹配 com.shuai包下的所有类的所有⽅法。
  • execution(* com.shuai..*.*(..)) :匹配 com.shuai包下、⼦孙包下所有类的所有⽅法。
  • execution(* com.shuai.demo.addUser(String, int)) :匹配 addUser ⽅法,且第⼀个参数类型是 String,第⼆个 参数类型是 int
  • ...

5.实例:SpringAOP实现统计方法执行时间

@Aspect    //告诉SpringAOP这是一个切面类
@Component //将其加入到Spring中进行管理
@Slf4j    //这里握住主要使用了其中的日志对象
public class UserAspect {

    @Pointcut("execution(String com.example.demo.controller.UserController.*(..)")
    public void getExecuteTime() {

    }

    /**
     * 统计UserController中的testAdvice方法的执行时间
     * @param joinPoint
     * @return  
     */
    @Around("getExecuteTime()")
    public Object timeAround(ProceedingJoinPoint joinPoint) {
        // 定义返回对象、得到方法需要的参数
        Object obj = null;
        Object[] args = joinPoint.getArgs();
        long startTime = System.currentTimeMillis();

        try {
            obj = joinPoint.proceed(args);
        } catch (Throwable e) {
            log.error("统计某方法执行耗时环绕通知出错", e);
        }

        // 获取执行的方法名
        long endTime = System.currentTimeMillis();
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        String methodName = signature.getDeclaringTypeName() + "." + signature.getName();

        // 打印耗时的信息
        log.info(methodName + "执行了: " + (endTime - startTime) + "ms");
        return obj;
    }
}

 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【HR专用】Vue+SpringBoot,实现人才招聘库的开发(后端部分)

人才招聘库是企业用于储存和管理潜在候选人信息的数据库。通常情况下&#xff0c;这些候选人可能已经应聘过公司的职位&#xff0c;也可能是通过其他途径获取的&#xff0c;例如社交网络、招聘网站等。 对于一个中小公司来说&#xff0c;人力资源部绝对是一个重要部门&#xff…

测试类型(单元、集成、系统或手动测试)

测试类型(单元、集成、系统或手动测试) 单元测试 单元是系统的单个组件&#xff0c;例如类或单个方法。孤立地测试单元称为单元测试。 优点&#xff1a;速度快/易控/易写 缺点&#xff1a;缺乏现实性/无法捕获所有错误&#xff08;例如与其他组件或服务的交互&#xff09; 单元…

Arthas-JVM相关命令使用

tip&#xff1a;作为程序员一定学习编程之道&#xff0c;一定要对代码的编写有追求&#xff0c;不能实现就完事了。我们应该让自己写的代码更加优雅&#xff0c;即使这会费时费力。 开头&#xff1a; 我们先说下生产使用频率较高的有哪些&#xff1a;dashboard、heapdump、jvm…

【连续介质力学】二阶张量的图像表示

二阶张量在特定方向的投影 法向和切向分量 二阶张量T投影到 n ^ \hat n n^方向的结果是 t ⃗ ( n ^ ) T ⋅ n ^ \vec t^{(\hat n)}T \cdot \hat n t (n^)T⋅n^&#xff0c;其中 t ⃗ ( n ^ ) \vec t^{(\hat n)} t (n^)可以分解成&#xff1a; t ⃗ ( n ^ ) T ⃗ N T ⃗ S…

2023年上半年系统规划与管理师上午真题及答案解析

1.香农用概率来定量描述信息的公式如下&#xff0c;其中H(x)表示X的( )&#xff0c;Pi是( )出现第i种状态的( )。 A.信息熵 事件 概率 B.总熵 单位 概率 C.信息熵 单位 概率 D.总熵 单位 度量 2.信息传输模型中&#xff0c;( )负责信息的向外传播&#xff0c;( )负责…

VSLAM视觉里程计总结

相机模型是理解视觉里程计之前的基础。视觉里程计&#xff08;VIO&#xff09;主要分为特征法和直接法。如果说特征点法关注的是像素的位置差&#xff0c;那么&#xff0c;直接法关注的则是像素的颜色差。特征点法通常会把图像抽象成特征点的集合&#xff0c;然后去缩小特征点之…

Android 应用快捷ShortcutManager与ShortcutManagerCompat详解与实战(二)

一、介绍 之前我已通过一篇文章介绍了应用快捷的接入与Demo。如果还未看过上一篇的文章可以先了解入门。 传送门&#xff1a;Android 应用快捷(shortcut)功能的详解(一)_蜗牛、Z的博客-CSDN博客 有创建自然就会有管理&#xff0c;否则一个完美的方案不应该这么被推荐出来。如何…

Zemax Lumerical | 二维光栅出瞳扩展系统优化(下)

简介 本文提出并演示了一种以二维光栅耦出的光瞳扩展&#xff08;EPE&#xff09;系统优化和公差分析的仿真方法。 在这个工作流程中&#xff0c;我们将使用3个软件进行不同的工作 &#xff0c;以实现优化系统的大目标。首先&#xff0c;我们使用 Lumerical 构建光栅模型并使用…

数据库实验报告--安全性实验

一、 实验目的 &#xff08;1&#xff09;理解SQL Server验证用户身份的过程&#xff0c;掌握设置身份验证模式的方法。 &#xff08;2&#xff09;理解登录账号的概念&#xff0c;掌握混合认证模式下登录账号的建立与取消方法。 &#xff08;3&#xff09;掌握混合认证模式…

Centos7中mysql安装配置

前提&#xff1a;先关闭防火墙或开启tcp的3306端口 1、查看服务器上是否有现成的安装包 yum list mysql* 2、去mysql官网的yum资源库找到对应的rpm文件的下载链接 确定系统版本 cat /etc/redhat-release 到mysql官网复制对应版本的资源下载链接 MySQL :: Download MySQL Yum…

git Husky

虽然我们已经要求项目使用eslint了&#xff0c;但是不能保证组员提交代码之前都将eslint中的问题解决掉了&#xff1a; 也就是我们希望保证代码仓库中的代码都是符合eslint规范的&#xff1b; 那么我们需要在组员执行 git commit 命令的时候对其进行校验&#xff0c;如果不符合…

说说验证码功能的实现

前言 大家好&#xff0c;我是 god23bin&#xff0c;今天说说验证码功能的实现&#xff0c;相信大家都经常接触到验证码的&#xff0c;毕竟平时上网也能遇到各种验证码&#xff0c;需要我们输入验证码进行验证我们是人类&#xff0c;而不是机器人。 验证码有多种类型&#xff…

项目中使用es(一):使用springboot操作elasticsearch

使用springboot操作es 写在前面搭建项目环境和选择合适版本具体的代码实现&#xff08;1&#xff09;继承ProductInfoRepository具体的代码实现&#xff08;2&#xff09;使用ElasticsearchRestTemplate操作问题总结最后放个demo 写在前面 对于elasticsearch的搭建&#xff0c…

5款提高工作效率的无广告软件

今天推荐一些可以大幅度提升办公效率的小软件&#xff0c;安全无毒&#xff0c;下载简单&#xff0c;最重要的是没有广告&#xff01; 1.照片处理——Darktable Darktable是一款用于处理和管理数码照片的工具。它可以让你对RAW格式的照片进行非破坏性的编辑,并提供多种模块和…

设计模式之~观察者模式

观察者模式又叫做发布-订阅&#xff08;Publish/Subscribe&#xff09;模式。 观察者模式observer&#xff1a;定义了一种一对多的依赖关系&#xff0c;让多个观察者对象同时监听某个主题对象。这个主题对象在状态发生变化时&#xff0c;会通知所有观察者对象&#xff0c;使他们…

Linux系统下imx6ull QT编程—— C++构造函数、析构函数、this指针(四)

Linux QT编程 文章目录 Linux QT编程一、什么是构造函数&#xff1f;二、什么是析构函数&#xff1f;三、示例四、this指针 一、什么是构造函数&#xff1f; 构造函数在对象实例化时被系统自动调用&#xff0c;仅且调用一次。前面我们学过类&#xff0c;实际上定义类时&#x…

【Spring】— 动态SQL :<if>元素

动态SQL &#xff1a;元素 在MyBatis中&#xff0c;<if>元素是常用的判断语句&#xff0c;主要用于实现某些简单的条件选择。在实际应用中&#xff0c;我们可能会通过多个条件来精确地查询某个数据。 【示例8-1】下面通过一个具体的案例来演示元素的使用。 &#xff0…

基于RPC协议的接口自动化测试可以用Python语言实现

基于RPC协议的接口自动化测试可以用Python语言实现。下面是实现步骤&#xff1a; 1、安装依赖库&#xff0c;如protobuf、grpc。 2、编写.proto文件定义接口参数和返回值。 3、使用protoc编译.proto文件生成Python代码。 4、编写客户端代码调用远程接口进行测试。 具体实现…

数据结构与算法练习(三)二叉树

文章目录 1、树2、二叉树3、满二叉树4、完全二叉树5、二叉树的遍历&#xff08;前序、中序、后序&#xff09;二叉树删除节点或树 6、顺序存储二叉树顺序存储二叉树遍历&#xff08;前序、中序、后序&#xff09; 7、线索化二叉树中序线索二叉树前序线索二叉树后序线索二叉树 1…

悲观锁、乐观锁、自旋锁

悲观锁、乐观锁、自旋锁 &#xff08;1&#xff09;乐观锁 乐观锁是一种乐观的思想&#xff0c;即认为读多写少&#xff0c;遇到并发的可能性低&#xff0c;每次拿数据时都认为别人不会修改&#xff0c;所以不会上锁&#xff0c;但是在更新的时候会判断一下在此期间别人有没有…