IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> SpringBoot中使用AOP -> 正文阅读

[Java知识库]SpringBoot中使用AOP

SpringBoot中使用AOP


AOP是通过动态代理实现的,动态代理又分为两个部分:JDK动态代理 和 CGLIB动态代理,以下两点需要记住:

1、AOP基于动态代理模式。
2、AOP是 方法级别 的。即,在方法执行的前,后,执行过程中,报错,返回结果等等流程中进行特殊操作

maven依赖

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

这里可以不用指定版本号, 在SpringBoot 的 parent 包里面有版本的控制。

示例

  1. 可以代理指定包中的方法 通过 execution 表达式
  2. 可以代理方法上加了注解的
import java.lang.annotation.*;

/**
 * desc: 自定义注解
 *
 * @author qts
 * @date 2022/4/21 0021
 */
@Documented
@Target({ElementType.TYPE,ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface MyAnnotation {

    String value() default "";

    String myValue() default "我是自定义注解";

}

import lombok.extern.slf4j.Slf4j;
import org.aopalliance.intercept.Joinpoint;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
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;
import java.util.Arrays;

/**
 * desc: 测试 aop
 *
 * @author qts
 * @date 2022/4/21 0021
 */
@Aspect
@Component
@Slf4j
public class MyAop {

    @Pointcut("@annotation(com.intellsite.business.util.MyAnnotation)")
    public void testMyAnnotationAspect() {}

    /**
     * 前置通知,目标方法调用前被调用
     * 除@Around外,每个方法里都可以加或者不加参数JoinPoint。
     * JoinPoint包含了类名、被切面的方法名、参数等属性。
     * @annotation中的值,需要和方法参数名相同
     **/
    //@Before(value = "testMyAnnotationAspect()") // 注解无参数 写法
    @Before(value = "testMyAnnotationAspect() && @annotation(myAnnotation)") // 注解带参数 写法
    public void before(JoinPoint joinpoint,MyAnnotation myAnnotation) {
        log.info("AOP before 执行 ...: 参数类型 {},name:{}",joinpoint.getArgs(),joinpoint.getSignature().getName());

        log.info("before-value ==" + myAnnotation.value() + ", before-myValue == " + myAnnotation.myValue());

        // 接收到请求,记录请求内容
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();

        // 记录请求内容
        System.out.println("URL : " + request.getRequestURL().toString());
        System.out.println("HTTP_METHOD : " + request.getMethod());
        System.out.println("IP : " + request.getRemoteAddr());
        System.out.println("CLASS_METHOD : " + joinpoint.getSignature().getDeclaringTypeName() + "." + joinpoint.getSignature().getName());
        System.out.println("ARGS : " + Arrays.toString(joinpoint.getArgs()));

    }

    /**
     * 前置通知,目标方法调用前被调用
     * 除@Around外,每个方法里都可以加或者不加参数JoinPoint。
     * JoinPoint包含了类名、被切面的方法名、参数等属性。
     * @annotation中的值,需要和方法参数名相同
     **/
    @Around(value = "testMyAnnotationAspect() && @annotation(myAnnotation))")
    public Object around(ProceedingJoinPoint proceedingJoinPoint, MyAnnotation myAnnotation) {
        try {
            log.info("AOP around 开始... 执行方法 ... : [ {} ], 参数为: [ {} ]",proceedingJoinPoint.getSignature().getName(),proceedingJoinPoint.getArgs());

            log.info("自定义注解值 value: " + myAnnotation.value() + "myValue: " + myAnnotation.myValue());

            Object proceed = proceedingJoinPoint.proceed();

            log.info("AOP around 结束... 执行方法 ... : [ {} ], 参数为: [ {} ]",proceedingJoinPoint.getSignature().getName(),proceedingJoinPoint.getArgs());

            return proceed;

        }catch (Throwable throwable) {
            log.info("AOP around 执行错误... error :{}", throwable.getMessage());
            throwable.printStackTrace();
            return "执行around出错。。。";
        }


    }

    /**
     * 最终通知,目标方法执行完之后执行
     **/
    @After(value = "execution(* com.intellsite.business.controller.AnnotationController.*(..))")
    public void after(JoinPoint joinPoint) {
        log.info("AOP after 执行... : {}",joinPoint.toLongString());
    }

    /**
     * 后置返回通知
     * 如果参数中的第一个参数为JoinPoint,则第二个参数为返回值的信息
     * 如果参数中的第一个参数不为JoinPoint,则第一个参数为returning中对应的参数
     * returning 只有目标方法返回值与通知方法具有相应参数类型时才能执行后置返回通知,否则不执行
     * 除了使用上面定义好的切面aspect(), 也可以直接使用表达式。
     **/
    @AfterReturning(value = "execution(* com.intellsite.business.controller.AnnotationController.getInfo(..)))",returning = "result")
    public void afterReturning(JoinPoint joinPoint,Object result) {
        log.info("AOP afterReturning 执行...  :返回结果:{}", result);
    }

    /**
     * 后置异常通知
     * 定义一个名字,该名字用于匹配通知实现方法的一个参数名,当目标方法抛出异常返回后,将把目标方法抛出的异常传给通知方法;
     * throwing 只有目标方法抛出的异常与通知方法相应参数异常类型时才能执行后置异常通知,否则不执行,
     **/
    @AfterThrowing(value = "testMyAnnotationAspect()",throwing = "exception")
    public void afterThrowing(JoinPoint joinPoint, Throwable exception) {
        log.error("AOP afterThrowing 执行... , msg : {}", exception.getMessage());
        if (exception instanceof NullPointerException) {

            log.info("空指针异常");
        }
    }
}

  1. 没抛异常的顺序
    正常: around开始 --》 before 执行–》afterReturning 执行–》after 执行–》around结束
  2. 异常时执行顺序
    异常: around开始–》before 执行–》afterThrowing 执行–》after 执行–》around

原文: https://www.cnblogs.com/dw3306/p/9615197.html

  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-04-23 10:43:02  更:2022-04-23 10:45:22 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/24 4:53:13-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码