AI

SpringBoot整合AOP

唐某2021-05-10 14:50:25153
  1. 认识AOP
    1.1 什么是AOP
    1.2 AOP中的概念
  2. SpringBoot整合AOP代码示例
    2.1 使用execution(路径表达式)
    2.2 使用annotation(注解)
  3. JoinPoint 对象
  4. ProceedingJoinPoint对象

1 认识Spring AOP

1.1 什么是AOP

AOP (Aspect Oiented Programn,面向切面编程)把业务功能分为核心、非核心两部分。

● 核心业务功能:用户登录、增加数据、删除数据。
● 非核心业务功能:性能统计、日志、事务管理。

在Spring的面向切面编程( AOP )思想里,非核心业务功能被定义为切面。核心业务功能和切面功能先被分别进行独立开发,然后把切面功能和核心业务功能“编织”在一起,这就是AOP。

未使用AOP的程序如 图1 所示,使用AOP的程序如 图2 所示。由此可见,AOP将那些与业务无关,却为业务模块所共同调用的逻辑封装起来,以便减少系统的重复代码,降低模块间的耦合度,利于未来的拓展和维护。这正是AOP的目的,它是Spring最为重要的功能之一,被广 泛使用。

在这里插入图片描述

1.2 AOP中的概念

● 切入点(pointcut):在哪些类、哪些方法上切入。

● 通知(advice):在方法前、方法后、方法前后做什么。

● 切面 = 切入点 + 通知。即在什么时机、什么地方、做什么。

● 织入(weaving):把切面加入对象,并创建出代理对象的过程

● 环绕通知(around):AOP中最强大、灵活的通知,它集成了前置和后置通知,保留了连接点原有的方法。

AOP的体系可以梳理为下图:
在这里插入图片描述

2 AOP代码示例

首先导入AOP的依赖

复制代码
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-aop</artifactId>
</dependency>

2.1 使用execution(路径表达式)

复制代码
@Slf4j
@Aspect
@Component
public class LogAspect {

    ThreadLocal<Long> startTime = new ThreadLocal<>();

    /**
     * execution函数用于匹配方法执行的连接点,语法为:
     * execution(方法修饰符(可选)  返回类型  方法名  参数  异常模式(可选))
     * 参数部分允许使用通配符:
     * *  匹配任意字符,但只能匹配一个元素
     * .. 匹配任意字符,可以匹配任意多个元素,表示类时,必须和*联合使用
     * +  必须跟在类名后面,如Horseman+,表示类本身和继承或扩展指定类的所有类
     */
    @Pointcut("execution(public * work.pcdd.aop_demo.controller.*.*(..))")
    private void webLog() {}

    /**
     * 前置增强
     */
    @Before("webLog()")
    public void doBefore(JoinPoint jp) {
        System.out.println("=====================doBefore======================");
        // 接收到请求
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        HttpServletRequest request = attributes.getRequest();

        // 记录请求内容
        log.info("URL : {}", request.getRequestURL());
        log.info("HTTP方法 : {}", request.getMethod());
        log.info("IP地址 : {}", request.getRemoteAddr());
        log.info("类的方法 : {}.{}", jp.getSignature().getDeclaringTypeName(), jp.getSignature().getName());
        log.info("方法参数 : {}", Arrays.toString(jp.getArgs()));
        System.out.println("=====================doBefore======================");
    }

    /**
     * 后置增强
     */
    @AfterReturning(pointcut = "webLog()", returning = "result")
    public void doAfterReturning(Object result) {
        System.out.println("=====================doAfterReturning======================");
        // 处理完请求,返回内容
        System.out.println("方法的返回值 : " + result);
        System.out.println("=====================doAfterReturning======================");
    }

    /**
     * 后置最终通知,最终增强,不管是抛出异常或者正

广告