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

总结

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

相关文章

  • Java 通过手写分布式雪花SnowFlake生成ID方法详解

    Java 通过手写分布式雪花SnowFlake生成ID方法详解

    SnowFlake是twitter公司内部分布式项目采用的ID生成算法,开源后广受国内大厂的好评。由这种算法生成的ID,我们就叫做SnowFlakeID,下面我们来详细看看
    2022-04-04
  • Spring中的aware接口详情

    Spring中的aware接口详情

    这篇文章主要介绍了Spring中的aware接口详情,Spring中有很多继承于aware中的接口,这些接口到底是做什么用到的,下面我们就一起来看看吧,文章详细内容需要的小伙伴可以参考一下
    2022-05-05
  • 使用Java填充Word模板的方法详解

    使用Java填充Word模板的方法详解

    Java填充Word模板是一种将动态数据插入到Word文档模板中生成最终文档的过程,通常用于批量创建包含个人信息、报告结果或其他动态内容的文档,本文给大家介绍了使用Java填充Word模板的方法,需要的朋友可以参考下
    2024-07-07
  • 详解springboot中mybatis注解形式

    详解springboot中mybatis注解形式

    在本文中小编给大家分享了关于springboot中mybatis注解形式的介绍,有兴趣的可以跟着学习下。
    2018-10-10
  • Spring注解解析之@ImportResource

    Spring注解解析之@ImportResource

    之前我们使用spring,最多的还是通过xml配置文件的方式来配置spring bean等内容,随着注解的广泛应用和spring4中Java config的引入,xml配置文件方式逐步被替换,但是如果是想要使用xml配置文件方式的话,也可以通过@ImportResource注解来实现,下面我们来一起看下如何使用.
    2021-05-05
  • Java 栈与队列超详细分析讲解

    Java 栈与队列超详细分析讲解

    这篇文章主要介绍了Java数据结构中的栈与队列,在Java的时候,对于栈与队列的应用需要熟练的掌握,这样才能够确保Java学习时候能够有扎实的基础能力。本文小编就来详细说说Java中的栈与队列,需要的朋友可以参考一下
    2022-04-04
  • Flyway详解及Springboot集成Flyway的详细教程

    Flyway详解及Springboot集成Flyway的详细教程

    Flayway是一款数据库版本控制管理工具,,支持数据库版本自动升级,Migrations可以写成sql脚本,也可以写在java代码里。这篇文章主要介绍了Flyway详解及Springboot集成Flyway的详细教程的相关资料,需要的朋友可以参考下
    2020-07-07
  • springboot2.0以上调度器配置线程池的实现

    springboot2.0以上调度器配置线程池的实现

    这篇文章主要介绍了springboot2.0以上调度器配置线程池的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-12-12
  • Springboot自动加载配置的原理解析

    Springboot自动加载配置的原理解析

    Springboot遵循“约定优于配置”的原则,使用注解对一些常规的配置项做默认配置,减少或不使用xml配置,让你的项目快速运行起来,这篇文章主要给大家介绍了关于Springboot自动加载配置原理的相关资料,需要的朋友可以参考下
    2021-10-10
  • 基于Mybatis的配置文件入门必看篇

    基于Mybatis的配置文件入门必看篇

    这篇文章主要介绍了Mybatis的配置文件入门,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-07-07

最新评论