Spring基础:AOP入门理解与使用

问题:什么是AOP?

  • AOP:面向切面编程
    • 主要目的是为了解耦,相当于拦截器。
    • 它可以让一组类共享相同的行为。

问题:AOP织入时机?

  • 编译时织入
    • AspectJ
  • 类加载时织入
    • AspectJ 5+ 和 AspectWerkz
  • 运行时织入
    • Spring AOP

问题:Spring AOP的代理模式是怎样的?

Spring AOP是动态代理:

  • 如果目标对象实现了接口,则默认采用JDK动态代理
  • 如果目标对象没有实现接口,则采用CGlib进行动态代理

问题:Spring AOP如何使用?

主要注解:

  • @Aspect:声明一个注解,用于类上,该类必须是Bean
  • @Pointcut:定义要拦截的地方(包、类、方法),支持切面表达式
  • Advice:
    • @Before:前置通知
    • @After:最终通知,方法执行完之后
    • @AfterReturning:返回通知,成功执行之后
    • @AfterThrowing:异常通知,抛出异常之后
    • @Around:环绕通知,包括了上面所有注解的能力
      • 它具有改变拦截目标的返回值功能

问题:切面表达式如何构造?

Wildcards(通配符)

  • “*”:匹配任意数量字符
  • “+”:匹配指定类及其子类
  • “…”:一般用于匹配任意数的子包或参数

Operators(运算符)

  • “&&”:与操作符
  • “||”:或操作符
  • “!”:非操作符

Designators(匹配方式)

  • 匹配方法
    • execution()
  • 匹配注解
    • @target()
    • @args()
    • @annotation()
  • 匹配包/类型
    • @within()
  • 匹配对象
    • this()
    • bean()
    • target()
  • 匹配参数
    • args()

简单使用示例:

  • 引入依赖:基于SpringBoot
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-aop</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>
  • 构造控制器
package com.example.springaoptest.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author Miracle
 * @date 2021/5/4 18:07
 */
@RestController
@RequestMapping("/test")
public class TestController {

    @GetMapping("/one")
    public String test1(){
        return "SUCCESS";
    }

}

  • 构造切面:
package com.example.springaoptest;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

/**
 * @author Miracle
 * @date 2021/5/4 18:03
 */
@Aspect
@Component
public class AspectTest {

    /**
     * 设定切面拦截位置,
     * 第一个“*”表示任意类
     * 第二个“*”表示任意方法
     * 括号内的“..”表示任意参数
     */
    @Pointcut("execution(public * com.example.springaoptest.controller.*.*(..))")
    public void recordLog(){
    }

    /**
     * 进入目标方法前拦截
     * @param joinPoint
     */
    @Before("recordLog()")
    public void recordLogBefore(JoinPoint joinPoint){
        System.out.println("方法进入前执行");
    }

    /**
     * 目标方法成功返回拦截
     * @param result
     */
    @AfterReturning(returning = "result" ,pointcut = "recordLog()")
    public void recordLogAfter(String result){
        System.out.println("方法返回值:" + result);
    }

    /**
     * 目标方法触发异常拦截
     * @param ex
     */
    @AfterThrowing(throwing = "ex", pointcut = "recordLog()")
    public void recordLogAfterThrow(Throwable ex){
        System.out.println("方法异常:" + ex.getMessage());
    }

    /**
     * 目标方法无论成功与否,执行完毕都触发拦截
     */
    @After("recordLog()")
    public void recordLogAfterFinal(){
        System.out.println("方法最终执行");
    }

    /**
     * 环绕拦截,不能与上面的注解一起使用
     * @param pjp
     */
    //@Around("recordLog()")
    public void recordLogAround(ProceedingJoinPoint pjp){
        System.out.println("环绕执行:"  );
    }

}

  • 执行效果:
    Spring基础:AOP入门理解与使用_第1张图片

代码下载链接:

https://download.csdn.net/download/k295330167/18377318?spm=1001.2014.3001.5501

你可能感兴趣的:(Spring基础,aop,spring)