自定义 Spring AOP 切面实战(鉴权、记录日志)

前言:

从事 Java 的小伙伴都知道 Spring AOP,也都知道 AOP 是面向切面编程,那你知道 AOP 在项目实战中怎么使用吗?本篇简单分享 Spring AOP 在项目中的实际使用。

AOP 知识储备传送门:

深入理解 Spring AOP 源码分析(附源码分析)

AOP 基础知识回顾

AOP 概念

  • 连接点(Join point):能够被拦截的地⽅、地点,Spring AOP 是基于动态代理的,所以是⽅法拦截的,每个成员⽅法都可以称之为连接点。
  • 切点(Poincut):匹配连接点的断言,在AOP中通知和一个切入点表达式关联,切点分为execution方式和annotation方式,前者可以用路径表达式指定哪些类织入切面,后者可以指定被哪些注解修饰的代码织入切面。
  • 通知(Advice):在切面的某个特定的连接点上执行的动作,通知分为:前置通知、后置通知、异常通知、最终通知、环绕通知(切面要完成的功能)。
  • 织⼊(Weaving):把切面连接到其它的应用程序类型或者对象上,并创建一个被通知的对象,分为:编译时织入、类加载时织入、执行时织入
  • 引⼊/引介(Introduction):允许我们向现有的类添加新⽅法或属性,是⼀种特殊的增强。
  • 切面(Aspect):切⾯由切点和增强、通知组成,它既包括了横切逻辑的定义、也包括了连接点的定义。

通知(Advice)分类

  • 前置通知(Before Advice):在⽬标⽅法被调⽤前的通知功能。
  • 后置通知(After Advice):在⽬标⽅法被调⽤之后的通知功能。
  • 返回通知(After-returning):在⽬标⽅法成功执⾏之后的通知功能。
  • 异常通知(After-throwing):在⽬标⽅法抛出异常之后的通知功能。
  • 环绕通知(Around):把整个⽬标⽅法包裹起来,在被调⽤前和调⽤之后的通知功能。

自定义 AOP 切面常用知识储备

@Aspect 注解的作用?

@Aspect 注解的作用是定义一个切面,需要再自定义切面类上加上次注解。

@Component 注解

@Component 注解表示这个类交给 Spring 容器管理,如果不使用 @Component 注解,也要以其他方法是注册切面类,以确保 Spring 容器能够识别并管理这个切面。

Pointcut 切点中 execution 和 @annotation 定义切面的区别?

  • @annotation:切点表达式是注解的全限类名,是根据注解来匹配的,有注解的方法才会被拦截。

  • execution:切点表达式很灵活,有修饰符匹配、返回值匹配、类路径匹配、方法名匹配、参数匹配、异常类型匹配。

  • 作用于任意以 public 修饰的方法:execution(public * *(…))

  • 作用于任何一个以 set 开始的方法:execution(* set*(…))

  • 作用于 MyService 接口的任意方法:execution(* com.xxx.service.MyService.*

  • 作用于定义在 service 包和所有子包里的任意类的任意方法:execution(* com.xxx.service….(…)),第一个 * 表示匹配任意的方法返回值, …(两个点)表示零个或多个,第一个 … 表示 service 包及其子包,第二个 * 表示所有类,第三个 * 表示所有方法,第二个…表示方法的任意参数个数。

JoinPoint 的作用?

PoinPoint 代表程序中的一个点,通常把 JoinPoint 作为一个参数传递到通知方法中,通过 JoinPoint 来获取程序中这个点的相关信息,JoinPoint 只能用于 @Before、@After、@AfterReturning、@AfterThrowing 通知中,不能使用于 @Around 中,JoinPoint 常用方法如下:

  • Object[] getArgs():返回目标方法的参数。
  • Signature getSignature():返回方法的签名。
  • Object getTarget():返回被增强的目标对象,也就是被代理对象。
  • Object getThis():返回由目标对象生成的代理对象。

ProceedingJoinPoint 的作用?

ProceedingJoinPoint 是 JoinPoint 的子接口,用于环绕通知 @Around 中,它提供了一个 proceed() 方法,用于执行被拦截的方法也就是目标方法。

自定义 AOP 切面代码演示

自定义 AOP 切面实现接口请求日志记录

记录接口请求日志这种业务场景是非常常见的,如果在每个接口中去记录,显得代码臃肿且不灵活,而且有很大的侵入性,我们可以使用自定义 AOP 面来完成这种功能,代码如下:

@Slf4j
@Component
@Aspect
public class MyApiLogAspect implements Ordered {
   

    @Pointcut("execution(* com.my.study.controller..*(..))")
    public void logPointCut() {
   

    }

    @Around("logPointCut()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
   
  
        long startTime = System.currentTimeMillis()
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值