【Spring AOP】Spring AOP快速使用

news2024/9/30 9:37:57

文章目录

      • 前言
      • 1、相关注解
        • 类注解
        • 方法注解
      • 2、execution 表达式
        • 例一【execution 表达式 的限制使用】
        • 例二【execution 表达式 的通配使用】
      • 3、相关pom依赖
      • 4、案例
        • 创建接口
        • Aop使用 方式一【@Before 、@After 、@AfterRuturning、@AfterThrowing版】
        • Aop使用 方式二【@Around版】

前言

Aop 是面向切面编程,项目中一般都使用aop做日志、权限等操作,比如我们想要打印所有接口的日志,就可以用Aop来实现。
下面用一个打印接口的日志来讲述Aop的快速使用。

如果你不想知道Aop的一些具体注解的单独讲述,可以直接进入到案例,案例中也会对Aop的注解做讲述和使用。


1、相关注解

类注解

  • @Aspect :表明是一个切面类;

方法注解

  • @Pointcut :切入点,该注解表示从哪里做切入;
  • @Before :前置通知,在切入点之前执行,可以理解成调用接口或者方法之前执行;
  • @After :后置通知,在切入点之后执行,可以理解成调用完该接口或者方法之后执行;
  • @AfterRuturning :返回通知,可以理解成调用完该接口或者方法返回结果之后执行;
  • @AfterThrowing :异常通知,可以理解成调用该接口或者方法时出现异常之后执行;
  • @Around :环绕通知,可以理解成这一个注解用来控制调用接口或方法;

2、execution 表达式

execution 表达式 写法是:访问修饰符 返回值 包名.包名.包名…类名.方法名(参数列表)


例一【execution 表达式 的限制使用】

下面这个例子,展示一些详细的使用

execution(public com.api.controller.User.findUserByUserId(..))

public 是该方法的返回值
com.api.controller 是该类所在的包位置
User 是类名
findUserByUserId 是该类的方法名
(..) 这个是参数,.. 表示通配所有参数


例二【execution 表达式 的通配使用】

execution(* com.api.controller..*.*(..))

第一个 * 是通配返回值
com.api.controller 是该类所在的包位置
.* 是通配com.api.controller这个包下所有的类
* 是类中所有方法
(..) 表示通配所有参数


3、相关pom依赖

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

4、案例

在做案例之前,先创建一个测试接口,方便测试Aop。

创建接口

package com.api.controller;

import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

@Slf4j
@RequestMapping("/user")
@RestController
public class UserController {

    @GetMapping("/findUserByUserId")
    public String findUserByUserId(@RequestParam(value = "userId") String userId) {
        log.info("进入 findUserByUserId 接口 参数userId: {}", userId);
        return "findUserByUserId 接口 返回的数据";
    }

}

Aop使用 方式一【@Before 、@After 、@AfterRuturning、@AfterThrowing版】

package com.api.aop;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;


@Component
@Aspect
@Slf4j
public class AOPTest {

    // @Pointcut 注解的作用就是要根据一种规则切入到某个位置, 我在这里使用的是 execution 表达式规则
    @Pointcut("execution(* com.api.controller..*.*(..))")
    public void pointcut() {
    }

    /***
     * 前置通知
     */
    @Before("pointcut()")
    public void deBefore(JoinPoint joinPoint) {
        log.info("前置通知");
        log.info("参数 {}", joinPoint.getArgs());
        final Signature signature = joinPoint.getSignature();
        log.info("接口名称 name {}", signature.getName());
        log.info("类名 declaringTypeName {}", signature.getDeclaringTypeName());

        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();
        log.info("接口地址 {}", request.getRequestURL().toString());
        log.info("接口请求方式 {}", request.getMethod());

    }

    /***
     * 后置通知
     */
    @After("pointcut()")
    public void after(JoinPoint joinPoint){
        log.info("后置通知");
    }

    /***
     * 返回结果通知
     */
    @AfterReturning(returning = "o", pointcut = "pointcut()")
    public void afterReturning(Object o) {
        log.info("返回结果通知");
        log.info("结果 {}", o);
    }

    /***
     * 异常通知
     */
    @AfterThrowing(throwing = "e", pointcut = "pointcut()")
    public void afterThrowing(JoinPoint joinPoint, Exception e){
        log.info("异常通知");
        log.info("产生异常的方法 {}", joinPoint);
        log.info("异常种类 {}", e);
    }
}

接下来调用一下刚刚写的接口,打印日志如下:

在这里插入图片描述

执行顺序图如下:

在这里插入图片描述

先进入前置通知,执行接口,如果接口中出现异常就进入异常通知,无异常进入结果通知,最后进入后置通知。


Aop使用 方式二【@Around版】

package com.api.aop;

import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;


@Component
@Aspect
@Slf4j
public class AOPTest {

    // @Pointcut 注解的作用就是要根据一种规则切入到某个位置, 我在这里使用的是 execution 表达式
    @Pointcut("execution(* com.api.controller..*.*(..))")
    public void pointcut() {
    }

    @Around("pointcut()")
    public Object Around(ProceedingJoinPoint joinPoint) {
        log.info("前置通知");
        log.info("参数 {}", joinPoint.getArgs());
        final Signature signature = joinPoint.getSignature();
        log.info("接口名称 name {}", signature.getName());
        log.info("类名 declaringTypeName {}", signature.getDeclaringTypeName());
        Object proceed = null;
        try {
            // 进入接口
            proceed = joinPoint.proceed();
            log.info("返回结果通知");
            
        } catch (Throwable throwable) {
            log.info("异常通知");
            throw new RuntimeException(throwable);
            
        } finally {
            log.info("后置通知");
            
        }

        return proceed;
    }
}

接下来调用一下刚刚写的接口,打印日志如下:

在这里插入图片描述





End


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

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

相关文章

【笔记】通过labview调用halcon

使用原因&#xff1a;手眼标定使用halcon的九点标定&#xff0c;但是整体系统是用labview的&#xff0c;机器人得到二维坐标后&#xff0c;需经过halcon算子计算得到机器人坐标系下坐标&#xff0c;在进行运动。 下载路径&#xff1a; 链接&#xff1a;https://pan.baidu.com/s…

「计算机组成原理」数据的表示和运算(上)

文章目录一、进位计数制1.1 其他进制转十进制1.2 十进制转其他进制1.3 二进制、八进制和十六进制1.3 真值和机器数二、BCD码2.1 8421码2.2 余3码2.3 2421码三、整数的表示和运算3.1 无符号整数3.1.1 无符号整数的表示3.1.2 无符号整数的运算3.2 有符号整数3.2.1 有符号整数的表…

聚观早报 | 微信也要下场做“外卖”?;《羊了个羊》营收破亿

今日要闻&#xff1a;微信也要下场做“外卖”&#xff1f;;《羊了个羊》营收破亿&#xff1b;苹果将新XR头显上市推迟至6月&#xff1b;“交个朋友”被爆欠薪暴力裁员&#xff1f;&#xff1b;微软解释ChatGPT Bing AI推出速度缓慢的原因微信也要下场做“外卖”&#xff1f;腾讯…

C语言返回类型为指针的一些经典题目(上)

大家好&#xff0c;今天和大家分享一下C语言返回类型为指针的一些重要题目&#xff0c;看完你会恍然大悟。原来我对指针的了解还停留在指针只是一个地址的位置上&#xff0c;看完后你会对指针的用法进一步得到提升。目录一.关于指针类型的基础概念二.题目剖析一.关于指针类型的…

Java反序列化漏洞——CommonsCollections6链分析

一、前因因为在jdk8u71之后的版本中&#xff0c;sun.reflect.annotation.AnnotationInvocationHandler#readObject的逻辑发生了变化&#xff0c;导致CC1中的两个链条都不能使用&#xff0c;所有我们需要找一个在高版本中也可用的链条。/* Gadget chain: java.io.ObjectInputStr…

35岁危机

人们对社会的期望是不断变更的&#xff0c;无论拥有高技能的人还是普通的白领&#xff0c;这种期望都让人们不断地励磁进步&#xff0c;以期实现自己的理想。但是&#xff0c;当人们达到35岁时&#xff0c;多数人就会陷入一种状态&#xff0c;这被称之为“35岁危机”。 在35岁…

时间轮和时间堆管理定时器

高性能定时器 时间轮 由于排序链表定时器容器有这样一个问题&#xff1a;添加定时器的效率偏低。而即将介绍的时间轮则解决了这个问题。一种简单的时间轮如下所示。 如图所示的时间轮内&#xff0c;指针指向轮子上的一个slot&#xff08;槽&#xff09;&#xff0c; 它以恒定…

Linux操作系统-线程互斥,线程同步,生产者消费者模型

线程互斥线程互斥及相关概念线程互斥&#xff08;Mutual Exclusion&#xff09;是指在多线程环境下&#xff0c;同一时刻只能有一个线程访问共享资源&#xff0c;以避免对该资源的不正确访问&#xff0c;造成数据不一致等问题。例如&#xff0c;如果有多个线程都要同时对同一个…

web端元素各种尺寸示意图

1.偏移尺寸 offsetHeight 元素在垂直方向上占用的尺寸(height,border,水平滚动条高度) offsetWidth 元素在垂直方向上占用的尺寸(height,border,水平滚动条高度) offsetTop 元素上边框外侧距离包含元素上边框内侧的尺寸 offsetLeft 元素左边框外侧距离包含元素左边框内侧的尺寸…

Python-第八天 Python文件操作

Python-第八天 Python文件操作一、文件的编码1. 什么是编码&#xff1f;2. 为什么需要使用编码&#xff1f;二、文件操作1.文件的操作步骤2. 打开文件3.mode常用的三种基础访问模式4.关闭文件三、文件的读取1.文件对象有如下读取方法&#xff1a;2.练习&#xff1a;单词计数三、…

nextTick 的使用和原理(面试题)

答题思路&#xff1a; nextTick 是做什么的&#xff1f;为什么需要它&#xff1f;开发时什么时候使用&#xff1f;介绍一下如何使用nextTick原理解读&#xff0c;结合异步更新和nextTick生效方式 1. nextTick是做什么的&#xff1f; nextTick是等待下一次DOM更新刷新的工具方法…

电子电器架构——怎样在请求/响应 ID确定的情况下修改发送FD 的CAN ID?

我是穿拖鞋的汉子,魔都中一个坚持长期主义的工程师! 老规矩,分享一段喜欢的文字,避免成为高知识低文化的人: 能不传话,最好不要传话;能不套话,最好不要套话;能不涉入“背后的批评”,最好不要涉入。让自己像沙滩,多大的浪来了,也是轻抚着沙滩,一波波地退去。而不要…

Ubuntu 快速切换到指定目录

现有以下场景&#xff0c;假设我在本地有/home/pc/Downloads/temp/Project 目录&#xff0c;我想快速在终端进入Project目录&#xff0c;需要怎么操作呢 文件管理器 由于我知道这个目录在哪个位置&#xff0c;那我就可以打开文件管理器&#xff0c;进入到这个目录&#xff0c…

关于数据治理ChatGPT是如何回答的?

这两天你的朋友圈是不是被火爆全网的ChatGPT霸屏了&#xff1f;你是不是已经迫不及待感受过ChatGPT带来的惊喜&#xff1f;那你知道ChatGPT是什么吗&#xff1f;面对掀起的一波话题热潮&#xff0c;好奇使然&#xff0c;小编去特别关注了一下最近火热的ChatGPT&#xff0c;看看…

基于Spring cloud搭建oauth2

1&#xff0c;OAuth2.0简介 OAuth&#xff08;开发授权&#xff09;是一个开放标准&#xff0c;允许用户授权第三方应用访问他们存储在另外的服务提供者上的信息&#xff0c;而不需要将用户名和密码提供给第三方应用或分享他们数据的所有内容。 OAuth2.0是OAuth的延续&#xf…

预告| 亮点抢先看!第四届OpenI/O启智开发者大会主论坛24日启幕!

2023年2月24日至25日&#xff0c;第四届OpenI/O启智开发者大会将在深圳隆重举行。“算网筑基、开源启智、AI赋能”作为今年大会的主题&#xff0c;吸引了全球业界关注的目光。大会集结中国算力网资源基座、开源社区治理及AI开源生态建设、国家级开放创新应用平台、NLP大模型等前…

2023年云计算的发展趋势如何?还值得学习就业吗?

一、2023年云计算的发展将迎来新篇章 随着政策的正式放开&#xff0c;2023年的经济开始慢慢复苏&#xff0c;云计算在疫情期间支撑了复工复产&#xff0c;那么在今年对于云计算发展的限制将进一步的放开。Gartner的数据显示&#xff0c;到2023年&#xff0c;全球公共云支出将达…

MybatisPlus------条件构造器Wrapper以及QueryWrapper用法(七)

MybatisPlus------条件构造器Wapper&#xff08;七&#xff09; Wrapper:条件构造器抽象类&#xff0c;最顶端父类 AbstarctWrapper&#xff1a;用于查询条件封装&#xff0c;生成sql的where条件。 QueryWrapper&#xff1a;查询条件封装&#xff08;可以用于查询、删除&#x…

Java必备小知识点1

Java程序类型: Applications和AppletApplications:是指在计算机操作系统中运行的程序。是完整的程序&#xff0c;能独立运行。被编译后&#xff0c;用普通的Java解释器就可以使其边解释边执行。必定含有一个main方法&#xff0c;程序执行时&#xff0c;首先寻找main方法&#x…

IDEA中如何配置SpringBoot项目多实例不同端口运行

1 问题场景 我们在进行新项目开发的时候&#xff0c; 可能做完一个新的模块功能并自测通过之后&#xff0c; 我们希望测试人员能帮我跑一些单元测试用例来进行测试验证&#xff0c; 但是我们又需要在此基础上技术开发新的功能&#xff0c; 这是我们就需要在我们的开发PC上同时…