欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

springboot AoP的使用方法

程序员文章站 2022-07-12 15:17:45
...

参考连接:https://blog.csdn.net/justry_deng/article/details/85065656

一、什么是AoP?

业务一般分为核心业务和其他业务,其他业务包括如日志监听、事务管理、权限控制等。如果核心业务开发完成后直接在原有代码基础上增加其他业务代码会导致代码的侵入性太强。这时候就需要AoP的思想编程了,也就是面向切面编程,可以无侵入性实现日志监听、事务管理和权限控制等非核心业务。

1、引入

在Springboot中pom.xml引入这个依赖就可以了:

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

2、使用

这里举个栗子:假设核心业务是一个接口,访问该接口返回一个结果比如是一个Json串,那么我想用入侵性最小的代价实现在返回这个Json串前后执行其他非核心业务功能

3、代码

假设核心业务代码就是这个Controller,直接返回一个类toString后的结果

@RestController
@RequestMapping("/api")
public class AopController {
    @PostMapping(value = "/test")
    public Map<String, Object> test(@RequestBody User user) {
        String threadName = Thread.currentThread().getName();
        System.out.println(threadName + " -> " + user.toString());
        Map<String,Object> map = new HashMap<>(8);
        map.put("params:",user.toString());
        map.put("code",0);
        map.put("message","SUCCESS");
        return map;
    }
}

然后我新建一个User类和AopConfig类

@Data
public class User {
    private String name;
    private int age;
}
@Aspect
@Component
public class AopConfig {
    @Pointcut("execution(* aoptest.controller.AopController.*(..))")
    public void executeAdvice(){

    }
    @Before(value = "executeAdvice()")
    public void beforeAdvice(JoinPoint joinPoint){
        Object[] paramArray = joinPoint.getArgs();
        String threadName = Thread.currentThread().getName();
        System.out.println(threadName + " -> beforeAdvice获取到了被增强方法的参数了,为:"
                + Arrays.toString(paramArray));

    }
    @After("executeAdvice()")
    public void afterAdvice() {
        String threadName = Thread.currentThread().getName();
        System.out.println(threadName + " -> 后置增强afterAdvice执行了");
    }

}

不管3721去打断点+Postman调试

springboot AoP的使用方法

springboot AoP的使用方法

springboot AoP的使用方法

如果没有AoP,肯定会进入Conller中的断点,但是使用了AoP你调试断点会发现:

进入Controller之前会先执行@Before下修饰的beforAdvice方法,然后执行Controller中的方法,但是controller中执行return之后呢,会继续执行@After后修饰的afterAdvice方法,这样上述代码才真正执行完毕。可以发现,我没有修改controller中的任何代码但是却可以实现在controller执行前后执行我想实现的一些功能,这就是AoP做到的。

springboot AoP的使用方法

 二、AoP基本概念

如果你执行了上述代码,估计对AoP功能有了一知半解,我们看一下AoP中的一些基本概念:参考https://www.cnblogs.com/liujiayun/p/5912628.html

1、join point(连接点):是程序执行中的一个精确执行点,例如类中的一个方法。它是一个抽象的概念,在实现AOP时,并不需要去定义一个join point。对应上面这段代码中的beforeAdvice中的参数

2、point cut(切入点):本质上是一个捕获连接点的结构。在AOP中,可以定义一个point cut,来捕获相关方法的调用。用法如下

springboot AoP的使用方法

其中execution里面的参数参考:https://blog.csdn.net/somilong/article/details/74568223https://blog.csdn.net/qq_39354297/article/details/99917138

语法:execution(修饰符(public/private等,可以省略)+返回值(不可省略,一般用通配符“*”)+包.类.方法+throws 异常(一般不写))

3、advice(通知):是point cut的执行代码,是执行“方面”的具体逻辑。包括“around,” “before” and "after"等多种类型。

4、aspect(切面):point cut和advice结合起来就是aspect,它类似于OOP中定义的一个类,但它代表的更多是对象间横向的关系。   

三、其他代码:

@Aspect
@Component
public class AopConfig {
    @Pointcut("execution(* aoptest.controller.AopController.*(..))")
    public void executeAdvice(){

    }
    @Before(value = "executeAdvice()")
    public void beforeAdvice(JoinPoint joinPoint){
        Object[] paramArray = joinPoint.getArgs();
        String threadName = Thread.currentThread().getName();
        System.out.println(threadName + " -> beforeAdvice获取到了被增强方法的参数了,为:"
                + Arrays.toString(paramArray));

    }
    @After("executeAdvice()")
    public void afterAdvice() {
        String threadName = Thread.currentThread().getName();
        System.out.println(threadName + " -> 后置增强afterAdvice执行了");
    }
    @AfterReturning(value = "executeAdvice()", returning = "map")
    public void afterReturningAdvice(Map<String, Object> map) {
        String threadName = Thread.currentThread().getName();
        System.out.println(threadName + " -> afterReturningAdvice获得了返回结果 map -> " + map);
    }
    @AfterThrowing(value = "executeAdvice()", throwing ="ex")
    public void afterThrowingAdvice(Exception ex) {
        System.out.println("AfterThrowing捕获到了 --->" + ex);
    }
    @Around("executeAdvice()")
    public Object aroundAdvice(ProceedingJoinPoint thisJoinPoint) throws Throwable {
        String threadName = Thread.currentThread().getName();
        System.err.println(threadName + " -> 环绕增强aroundAdvice --> before proceed()执行了");
        // 执行被增强方法,并获取到返回值
        // 类似于 过滤器的chain.doFilter(req,resp)方法
        Object obj = thisJoinPoint.proceed();
        System.err.println(threadName + " -> 环绕增强aroundAdvice --> after proceed()执行了");
        return obj;
    }
}

执行顺序可以参考:https://blog.csdn.net/qq_32331073/article/details/80596084 里面还介绍了不同切面Advice的执行顺序

springboot AoP的使用方法

相关标签: Java