SpringBoot面向切面变成AOP梳理

news/2024/11/8 18:48:43 标签: spring boot, java

1.概述

  • 在 Spring Boot 中,@Aspect是一个用于实现面向切面编程(AOP - Aspect - Oriented Programming)的注解。AOP 是一种编程范式,它允许开发者将横切关注点(如日志记录、性能统计、事务管理等)从业务逻辑中分离出来,从而使代码更加模块化、可维护和可重用。@Aspect注解用于标记一个类,表明这个类是一个切面(Aspect)。

2.创建切面类

  • 首先,需要创建一个带有@Aspect注解的 Java 类。例如:
java">import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class LoggingAspect {
    // 切面类中的方法用于定义切点和通知
}
  • 这里的@Aspect注解表明LoggingAspect是一个切面类,@Component注解则是为了让 Spring能够扫描并管理这个切面类,将其作为一个 Spring 组件。

3.定义切点(Pointcut)

  • 切点用于指定在哪些方法或类上应用切面逻辑。可以使用@Pointcut注解来定义切点。例如,以下是一个简单的切点定义,用于匹配某个包下的所有方法:
java">import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class LoggingAspect {
    @Pointcut("execution(* com.example.demo.service..*.*(..))")
    public void serviceMethods() {}
}
  • 在这个例子中,@Pointcut注解中的表达式execution(*
    com.example.demo.service….(…))是一个切点表达式。它表示匹配com.example.demo.service包及其子包下的所有类的所有方法,无论方法的返回值类型和参数列表如何。

4.定义通知(Advice)

  • 通知是切面中的具体逻辑,用于在切点所匹配的方法执行前后或出现异常时执行特定的操作。有以下几种类型的通知:
  • 前置通知
  • 前置通知(Before):在目标方法执行之前执行的通知。可以使用@Before注解来定义前置通知。例如:
java">import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class LoggingAspect {
    @Pointcut("execution(* com.example.demo.service..*.*(..))")
    public void serviceMethods() {}

    @Before("serviceMethods()")
    public void logBeforeServiceMethod() {
        System.out.println("在服务方法执行之前记录日志");
    }
}
  • 在这个例子中,@Before(“serviceMethods()”)表示在serviceMethods切点所匹配的方法执行之前,会执行logBeforeServiceMethod方法,这里只是简单地打印了一条日志。
  • 后置通知
  • 后置通知(After):在目标方法执行之后执行的通知。使用@After注解定义,如下:
java">import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class LoggingAspect {
    @Pointcut("execution(* com.example.demo.service..*.*(..))")
    public void serviceMethods() {}

    @After("serviceMethods()")
    public void logAfterServiceMethod() {
        System.out.println("在服务方法执行之后记录日志");
    }
}
  • 返回通知
  • 返回通知(AfterReturning):在目标方法正常返回之后执行的通知。使用@AfterReturning注解定义,并且可以获取目标方法的返回值。例如:
java">import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class LoggingAspect {
    @Pointcut("execution(* com.example.demo.service..*.*(..))")
    public void serviceMethods() {}

    @AfterReturning(pointcut = "serviceMethods()", returning = "result")
    public void logAfterReturningServiceMethod(Object result) {
        System.out.println("服务方法返回值为: " + result);
    }
}
  • 异常通知
  • 异常通知(AfterThrowing):在目标方法抛出异常时执行的通知。使用@AfterThrowing注解定义,可以获取抛出的异常对象。例如:
java">import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class LoggingAspect {
    @Pointcut("execution(* com.example.demo.service..*.*(..))")
    public void serviceMethods() {}

    @AfterThrowing(pointcut = "serviceMethods()", throwing = "ex")
    public void logAfterThrowingServiceMethod(Exception ex) {
        System.out.println("服务方法抛出异常: " + ex.getMessage());
    }
}

5.切面的执行顺序

  • 当有多个切面应用于同一个方法时,它们的执行顺序可以通过@Order注解来控制。例如:
java">import org.aspectj.lang.annotation.Aspect;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

@Aspect
@Component
@Order(1)
public class LoggingAspect {
    // 切面逻辑
}
  • 在这个例子中,@Order(1)表示这个切面的执行顺序为1。数字越小,执行顺序越靠前。如果没有指定@Order注解,切面的执行顺序是不确定的。

http://www.niftyadmin.cn/n/5744299.html

相关文章

代码中的设计模式-策略模式

假如我们有一段代码,有很多的if else function executeAction(type) {if (type A) {console.log(Action A);} else if (type B) {console.log(Action B);} else if (type C) {console.log(Action C);} else {console.log(Unknown action);} }executeAction(A); // 输出: Ac…

链表的归并排序

两种方法 递归法(自顶向下法) 迭代法(自底向上法) 递归法(自顶向下法) 这里链表与数组不同的是链表无法随机访问,在数组中我们都能精准的找到中间位置,这里我们采用快慢指针来确定中间节点,然后通过递归到单个元素然…

8+ 典型分析场景,25+ 标杆案例,Apache Doris 和 SelectDB 精选案例集(2024版)电子版上线

当前,各企业正面临前所未有的数据增量,不仅体现在数据规模的急剧上升,还体现在数据的类型多样性和产生速度的加快。数据体量大固然蕴藏着更大的潜力及可能性,但如何有效利用这些数据,解决实际问题、赋能业务增长&#…

夜天之书 #103 开源嘉年华纪实

上周在北京参与了开源社主办的 2024 中国开源年会。其实相比于有点明显班味的“年会”,我的参会体验更像是经历了一场中国开源的年度嘉年华。这也是在会场和其他参会朋友交流时共同的体验:在开源社的 COSCon 活动上,能够最大限度地一次性见到…

ArcGIS地理空间平台 manager 任意文件读取漏洞复现

0x01 产品描述: ‌ ArcGIS‌是一个综合的地理空间平台,由Esri开发,旨在为专业人士和组织提供全面的地理信息系统(GIS)功能。ArcGIS通过集成和连接地理环境中的数据,支持创建、管理、分析、映射和共享…

Spring Boot驱动的导师双选系统:设计与实现

第一章 绪论 1.1 选题背景 如今的信息时代,对信息的共享性,信息的流通性有着较高要求,尽管身边每时每刻都在产生大量信息,这些信息也都会在短时间内得到处理,并迅速传播。因为很多时候,管理层决策需要大量信…

安全工程师入侵加密货币交易所获罪

一名高级安全工程师被判犯有对去中心化加密货币交易所的多次攻击罪,在此过程中窃取了超过 1200 万美元的加密货币。 沙克布艾哈迈德(Shakeeb Ahmed)被判刑,美国检察官达米安威廉姆斯(Damian Williams)称其…

[全网最细数据结构完整版]第六篇:3分钟带你吃透栈并模拟实现

目录 1->栈的概念和结构 1.1栈的概念 1.2栈的结构 2->栈的实现 2.1定义关于栈的结构体和各种函数 2.2栈的初始化 STInit 函数 2.3栈的销毁 STDestroy 函数 2.4栈的插入操作 STPush 函数 2.5栈的判断是否为空操作 STEmpty 函数 2.6栈的删除操作 STPop 函数 2.7…