当前位置: 首页 > article >正文

理解spring中的AOP

Spring 框架中的 AOP(Aspect-Oriented Programming,面向切面编程)是一种编程范式,旨在通过将横切关注点(cross-cutting concerns)从业务逻辑中分离出来,从而提高模块化程度。横切关注点是指那些影响多个模块的功能,例如日志记录、事务管理、安全检查等。AOP 通过将这些关注点封装到切面(Aspect)中,使它们可以跨多个对象重用,而不会污染业务逻辑代码。

AOP 的核心概念

  1. 切面(Aspect):

    • 切面是关注点的模块化,例如日志记录或事务管理。切面可以看作是通知和切入点的集合。
    • 在 Spring 中,切面通常通过 @Aspect 注解来定义。
  2. 连接点(Join Point):

    • 连接点是在程序执行过程中可以插入切面的地方。例如,方法调用、异常抛出等。
    • 在 Spring AOP 中,连接点通常是方法执行。
  3. 通知(Advice):

    • 通知是在特定的连接点执行的代码。Spring AOP 支持多种类型的通知:
      • Before Advice (@Before): 在方法调用之前执行。
      • After Returning Advice (@AfterReturning): 在方法成功返回之后执行。
      • After Throwing Advice (@AfterThrowing): 在方法抛出异常之后执行。
      • After (Finally) Advice (@After): 无论方法是否成功完成,都会执行。
      • Around Advice (@Around): 在方法调用之前和之后执行,可以控制是否继续执行方法。
  4. 切入点(Pointcut):

    • 切入点定义了通知应该在哪些连接点上应用。通常使用表达式来指定。
    • 例如,execution(* com.example.service.*.*(..)) 表示匹配 com.example.service 包下所有类的所有方法。
  5. 引入(Introduction):

    • 引入允许向现有类添加新的方法或属性。这在 Spring AOP 中较少使用。

示例:Spring AOP 基本用法

假设我们有一个简单的服务类,我们希望在每个方法调用前后记录日志。

1. 添加依赖

确保你的项目中包含了 Spring AOP 的依赖。如果你使用的是 Spring Boot,通常只需要在 pom.xmlbuild.gradle 文件中添加 spring-boot-starter-aop 依赖。

Maven:

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

Gradle:

implementation 'org.springframework.boot:spring-boot-starter-aop'
2. 创建服务类
package com.example.demo.service;

import org.springframework.stereotype.Service;

@Service
public class UserService {

    public String getUserInfo() {
        return "User Information";
    }

    public void updateUser() {
        // 更新用户信息的逻辑
    }
}
3. 创建切面类
package com.example.demo.aspect;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

@Aspect
@Component
public class LoggingAspect {

    // Before Advice
    @Before("execution(* com.example.demo.service.UserService.*(..))")
    public void logBefore(JoinPoint joinPoint) {
        String methodName = joinPoint.getSignature().getName();
        System.out.println("Before method: " + methodName);
    }

    // After Returning Advice
    @AfterReturning(pointcut = "execution(* com.example.demo.service.UserService.getUserInfo(..))", returning = "result")
    public void logAfterReturning(JoinPoint joinPoint, Object result) {
        String methodName = joinPoint.getSignature().getName();
        System.out.println("Method " + methodName + " returned value: " + result);
    }

    // After Throwing Advice
    @AfterThrowing(pointcut = "execution(* com.example.demo.service.UserService.updateUser(..))", throwing = "ex")
    public void logAfterThrowing(JoinPoint joinPoint, Exception ex) {
        String methodName = joinPoint.getSignature().getName();
        System.out.println("Method " + methodName + " threw exception: " + ex.getMessage());
    }

    // After (Finally) Advice
    @After("execution(* com.example.demo.service.UserService.*(..))")
    public void logAfter(JoinPoint joinPoint) {
        String methodName = joinPoint.getSignature().getName();
        System.out.println("After method: " + methodName);
    }
}
4. 测试

创建一个控制器来测试服务类的方法:

package com.example.demo.controller;

import com.example.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class UserController {

    @Autowired
    private UserService userService;

    @GetMapping("/user")
    public String getUser() {
        return userService.getUserInfo();
    }

    @GetMapping("/update-user")
    public void updateUser() {
        userService.updateUser();
    }
}

运行应用

启动 Spring Boot 应用,并访问以下 URL:

  • http://localhost:8080/user 将调用 getUserInfo 方法。
  • http://localhost:8080/update-user 将调用 updateUser 方法。

你应该会在控制台看到相应的日志输出,验证 AOP 切面是否按预期工作。

总结

通过上述步骤,你可以成功地在 Spring Boot 应用中实现 AOP,从而将横切关注点(如日志记录)与业务逻辑分离,提高代码的模块化和可维护性。


http://www.kler.cn/a/383018.html

相关文章:

  • 【Linux驱动开发】timer库下的jiffies时间戳和延时驱动编写
  • 【pycharm jupyter】远程开发 启动报错
  • spark-on-k8s 介绍
  • vscode php Launch built-in server and debug, PHP内置服务xdebug调试,自定义启动参数配置使用示例
  • 批量图片转PDF文件的多种方法详解
  • 疯狂Java讲义-Java基础类库
  • git 提交代码流程
  • 递归 != 递龟
  • 和合共赢 丨 广州探迹科技有限公司与泰迪智能科技战略合作签约仪式圆满结束
  • Redis常见面试题(二)
  • 蓝牙协议的前世今生
  • 猫用空气净化器哪个牌子好?求除毛好、噪音小的宠物空气净化器!
  • 华为eNSP:QinQ
  • RTDE确保整个机械臂(包括关节和连杆)都不会进入预设的不安全空间范围
  • 02 高效调优:Oracle内存体系的精细化管理实践
  • 聚观早报 | 比亚迪腾势D9登陆泰国;苹果 iOS 18.2 将发布
  • HDFS和HBase跨集群数据迁移 源码
  • 【PGCCC】Postgresql slru 缓存和存储
  • 基于 Vue3、Vite 和 TypeScript 实现开发环境下解决跨域问题,实现前后端数据传递
  • 【人工智能】图神经网络(GNN)的原理与实现:Python与PyTorch Geometric在社交网络与化学分子建模中的应用
  • 前端八股文(二)CSS 持续更新中。。。
  • C++:继承及其相关问题
  • 国产MCU厂商第三季度取得亮眼成绩!
  • 新能源汽车与公共充电桩布局
  • 小华一级 代理商 HC32F005C6PA-TSSOP20 HC32F005系列
  • Neo4j 和 Python 初学者指南:如何使用可选关系匹配优化 Cypher 查询