SpringBoot如何使用@Aspect注解实现AOP

 更新时间:2023年07月28日 08:38:58   作者:wuychn  
这篇文章主要介绍了SpringBoot如何使用@Aspect注解实现AOP问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

使用@Aspect 注解实现AOP

AOP(Aspect Oriented Programming,面向切面编程)是通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。

AOP是OOP的延续,是软件开发中的一个热点,也是Spring框架中的一个重要内容,是函数式编程的一种衍生范型。

利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑各部分之间的耦合度降低,提高程序的可重用性,同时提高了开发的效率。

在Spring AOP中业务逻辑仅仅只关注业务本身,将日志记录、性能统计、安全控制、事务处理、异常处理等代码从业务逻辑代码中划分出来,从而在改变这些行为的时候不影响业务逻辑的代码。

相关注解介绍

注解作用
@Aspect把当前类标识为一个切面
@PointcutPointcut是织入Advice的触发条件。每个Pointcut的定义包括2部分,一是表达式,二是方法签名。方法签名必须是public及void型。可以将Pointcut中的方法看作是一个被Advice引用的助记符,因为表达式不直观,因此我们可以通过方法签名的方式为此表达式命名。因此Pointcut中的方法只需要方法签名,而不需要在方法体内编写实际代码。
@Around环绕增强,目标方法执行前后分别执行一些代码
@AfterReturning返回增强,目标方法正常执行完毕时执行
@Before前置增强,目标方法执行之前执行
@AfterThrowing异常抛出增强,目标方法发生异常的时候执行
@After后置增强,不管是抛出异常或者正常退出都会执行

一、添加依赖

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

二、编写增强类

package com.wuychn.springbootaspect.aspect;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;
@Aspect
@Component
@Slf4j
public class LogAspect {
    /**
     * 前置增强:目标方法执行之前执行
     *
     * @param jp
     */
    @Before("execution(* com.wuychn.springbootaspect.controller.*.*(..))") // 所有controller包下面的所有方法的所有参数
    public void beforeMethod(JoinPoint jp) {
        String methodName = jp.getSignature().getName();
        log.info("【前置增强】the method 【" + methodName + "】 begins with " + JSON.toJSONString(jp.getArgs()));
    }
    /**
     * 后置增强:目标方法执行之后执行以下方法体的内容,不管是否发生异常。
     *
     * @param jp
     */
    @After("execution(* com.wuychn.springbootaspect.controller.*.*(..)))")
    public void afterMethod(JoinPoint jp) {
        log.info("【后置增强】this is a afterMethod advice...");
    }
    /**
     * 返回增强:目标方法正常执行完毕时执行
     *
     * @param jp
     * @param result
     */
    @AfterReturning(value = "execution(* com.wuychn.springbootaspect.controller.*.*(..)))", returning = "result")
    public void afterReturningMethod(JoinPoint jp, Object result) {
        String methodName = jp.getSignature().getName();
        log.info("【返回增强】the method 【" + methodName + "】 ends with 【" + result + "】");
    }
    /**
     * 异常增强:目标方法发生异常的时候执行,第二个参数表示补货异常的类型
     *
     * @param jp
     * @param e
     */
    @AfterThrowing(value = "execution(* com.wuychn.springbootaspect.controller.*.*(..))", throwing = "e")
    public void afterThorwingMethod(JoinPoint jp, Exception e) {
        String methodName = jp.getSignature().getName();
        log.error("【异常增强】the method 【" + methodName + "】 occurs exception: ", e);
    }
    /**
     * 环绕增强:目标方法执行前后分别执行一些代码,发生异常的时候执行另外一些代码
     *
     * @return
     */
/*    @Around(value = "execution(* com.wuychn.springbootaspect.controller.*.*(..))")
    public Object aroundMethod(ProceedingJoinPoint jp) {
        String methodName = jp.getSignature().getName();
        Object result = null;
        try {
            log.info("【环绕增强中的--->前置增强】:the method 【" + methodName + "】 begins with " + Arrays.asList(jp.getArgs()));
            //执行目标方法
            result = jp.proceed();
            log.info("【环绕增强中的--->返回增强】:the method 【" + methodName + "】 ends with " + result);
        } catch (Throwable e) {
            result = "error";
            log.info("【环绕增强中的--->异常增强】:the method 【" + methodName + "】 occurs exception " + e);
        }
        log.info("【环绕增强中的--->后置增强】:-----------------end.----------------------");
        return result;
    }*/
}

三、Controller

package com.wuychn.springbootaspect.controller;
import com.wuychn.springbootaspect.entity.User;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@Slf4j
public class TestController {
    @GetMapping("/doNormal")
    public String doNormal(String name, String age, User user) {
        log.info("【执行方法】:doNormal");
        return "doNormal";
    }
    @GetMapping("/doWithException")
    public String doWithException(String name, String age, User user) {
        log.info("【执行方法】:doWithException");
        int a = 1 / 0;
        return "doWithException";
    }
}

启动程序,当访问doNormal方法时,

日志输出如下:

2019-05-13 14:36:20.931  INFO 12592 --- [nio-9379-exec-5] c.w.springbootaspect.aspect.LogAspect    : 【前置通知】the method 【doNormal】 begins with ["zhangsan","12",{"address":["chengdu","beijing"],"name":"zhangsan"}]
2019-05-13 14:36:20.932  INFO 12592 --- [nio-9379-exec-5] c.w.s.controller.TestController          : 【执行方法】:doNormal
2019-05-13 14:36:20.932  INFO 12592 --- [nio-9379-exec-5] c.w.springbootaspect.aspect.LogAspect    : 【后置通知】this is a afterMethod advice...
2019-05-13 14:36:20.932  INFO 12592 --- [nio-9379-exec-5] c.w.springbootaspect.aspect.LogAspect    : 【返回通知】the method 【doNormal】 ends with 【doNormal】

当访问doWithException方法时,

日志输出如下:

2019-05-13 14:45:03.699  INFO 12592 --- [nio-9379-exec-8] c.w.springbootaspect.aspect.LogAspect    : 【前置通知】the method 【doWithException】 begins with ["zhangsan","12",{"address":["chengdu","beijing"],"name":"zhangsan"}]
2019-05-13 14:45:03.699  INFO 12592 --- [nio-9379-exec-8] c.w.s.controller.TestController          : 【执行方法】:doWithException
2019-05-13 14:45:03.699  INFO 12592 --- [nio-9379-exec-8] c.w.springbootaspect.aspect.LogAspect    : 【后置通知】this is a afterMethod advice...
2019-05-13 14:45:03.704 ERROR 12592 --- [nio-9379-exec-8] c.w.springbootaspect.aspect.LogAspect    : 【异常通知】the method 【doWithException】 occurs exception: 
 
java.lang.ArithmeticException: / by zero

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • SpringBoot2零基础到精通之数据与页面响应

    SpringBoot2零基础到精通之数据与页面响应

    SpringBoot是一种整合Spring技术栈的方式(或者说是框架),同时也是简化Spring的一种快速开发的脚手架
    2022-03-03
  • 详解Java编程中protected修饰符与static修饰符的作用

    详解Java编程中protected修饰符与static修饰符的作用

    这篇文章主要介绍了Java编程中protected关键字与static关键字的作用,是Java入门学习中的基础知识,需要的朋友可以参考下
    2016-01-01
  • SpringBoot错误处理机制以及自定义异常处理详解

    SpringBoot错误处理机制以及自定义异常处理详解

    这篇文章主要为大家详细介绍了SpringBoot错误处理机制以及自定义异常处理,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2019-05-05
  • mybatisplus 多表关联条件分页查询的实现

    mybatisplus 多表关联条件分页查询的实现

    本文主要介绍了mybatisplus 多表关联条件分页查询的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2025-01-01
  • 面试题:Java中如何停止线程的方法

    面试题:Java中如何停止线程的方法

    这篇文章主要介绍了Java中如何停止线程的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-09-09
  • Java Comparator比较器实例解析

    Java Comparator比较器实例解析

    这篇文章主要介绍了Java Comparator比较器实例解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-01-01
  • Java MeteoInfo解析与绘图代码教程详解

    Java MeteoInfo解析与绘图代码教程详解

    这篇文章主要介绍了Java MeteoInfo解析与绘图代码教程,对于后端导出图片的话,就需要添加色阶了,这一文很简单,就涉及色阶,名称,网格刻度线,感兴趣的朋友一起看看吧
    2021-10-10
  • SpringBoot2.x的依赖管理配置

    SpringBoot2.x的依赖管理配置

    这篇文章主要介绍了SpringBoot2.x的依赖管理配置,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-06-06
  • java 创建线程的几种方式

    java 创建线程的几种方式

    本文主要介绍了java中创建线程的几种方式。具有很好的参考价值,下面跟着小编一起来看下吧
    2017-02-02
  • Idea servlet映射方法优缺点对比

    Idea servlet映射方法优缺点对比

    这篇文章主要介绍了Idea servlet映射方法优缺点对比,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-11-11

最新评论