Spring AOP

Spring AOP(Aspect-Oriented Programming)

        是Spring框架的一个重要特性,它提供了一种面向切面的编程模型,允许开发者将关注点(如日志、事务管理、安全性等)从核心业务逻辑中分离出来,实现代码的解耦。AOP通过在运行时动态地将代码插入到目标类的方法中,实现对方法执行前后的增强,这种插入的代码被称为通知(Advice)。

(1)AOP原理:

        1. 切面(Aspect):包含了横切关注点的模块,比如日志、事务管理等。在Spring AOP中,切面可以是单独的类,通常使用注解来标识。
        2. 通知(Advice):切面中定义的具体增强逻辑,比如方法执行前的记录日志、执行后的清理工作等。
        3. 连接点(Join Point):程序执行过程中的特定点,如方法的调用。
        4. 切入点(Pointcut):匹配连接点的规则表达式,用于指定哪些连接点会被通知逻辑所影响。
        5. 织入(Weaving):将切面应用到目标对象,创建代理的过程。Spring AOP可以在运行时(动态代理)或编译时(字节码增强)进行织入。

(2)案例:

下面是一个简单的Spring AOP案例,用于记录方法执行的时间:

1. 切面类(Aspect):LoggingAspect

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

/**
 * 日志切面类,用于记录服务方法的执行时间。
 * 使用了Spring的AOP注解来定义切面逻辑。
 */
@Aspect // 标记这是一个切面类
@Component // 让Spring容器管理这个切面
public class LoggingAspect {

    /**
     * 环绕通知,用于在方法执行前后记录时间。
     * @param joinPoint 连接点,包含正在执行的方法信息。
     * @return 方法执行的结果。
     * @throws Throwable 方法执行过程中可能抛出的异常。
     */
    @Around("execution(* com.example.service.*.*(..))") // 指定切入点表达式,匹配com.example.service包下的所有方法
    public Object logExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable {
        long start = System.currentTimeMillis();
        System.out.println(joinPoint.getSignature() + " 开始执行于 " + start); // 打印方法开始执行的时间
        
        // 执行目标方法
        Object result = joinPoint.proceed();
        
        long elapsedTime = System.currentTimeMillis() - start;
        System.out.println(joinPoint.getSignature() + " 结束执行,耗时 " + elapsedTime + "毫秒"); // 打印方法执行耗时
        
        return result; // 返回方法执行结果
    }
}

在execution表达式中,* com.example.service.*.*(..)表示匹配com.example.service包下的所有类的所有方法。 

2. 作为切面监控目标类:ExampleService

确保该类在com.example.service包下,当调用performTask方法时,LoggingAspect的logExecutionTime切面会介入,记录下这个方法的执行时间,从而展示了Spring AOP如何在不修改原有业务逻辑代码的情况下,增加如日志记录这样的横切关注点。

import org.springframework.stereotype.Service;

/**
 * 示例服务类,包含将被切面监控的方法。
 */
@Service // 标记为Spring管理的服务类
public class ExampleService {

    /**
     * 示例方法,模拟业务逻辑执行。
     */
    public void performTask() {
        try {
            Thread.sleep(100); // 模拟耗时操作
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            throw new RuntimeException(e);
        }
        System.out.println("执行任务完毕!"); // 打印任务完成信息
    }
}

 3. Spring 配置(如果使用Java配置)

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableAspectJAutoProxy;

/**
 * Spring配置类,启用AOP代理并配置切面。
 */
@Configuration
@EnableAspectJAutoProxy // 启用AspectJ自动代理,这是使用Spring AOP的关键
public class AppConfig {

    /**
     * 配置切面Bean。
     * @return LoggingAspect实例。
     */
    @Bean
    public LoggingAspect loggingAspect() {
        return new LoggingAspect();
    }

}

当调用com.example.service包下任何类的任何方法时,logExecutionTime方法将会在目标方法前后被调用,记录执行时间。

例如:在主应用中注入并调用ExampleService的performTask方法,然后观察控制台输出,你会发现除了"执行任务完毕!"之外,还会显示方法开始执行的时间和总耗时,这些都是由LoggingAspect切面自动添加的。

注意:如果已经在Spring配置中启用了AOP支持,例如通过@EnableAspectJAutoProxy注解。如果使用Spring Boot,通常默认就已经包含了对AOP的支持。

相关推荐

  1. SpringAOP的实现原理

    2024-06-07 17:34:01       53 阅读
  2. 一个简易的SpringAOP实例

    2024-06-07 17:34:01       55 阅读
  3. 浅谈SpringAOP实现原理

    2024-06-07 17:34:01       44 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-06-07 17:34:01       98 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-06-07 17:34:01       106 阅读
  3. 在Django里面运行非项目文件

    2024-06-07 17:34:01       87 阅读
  4. Python语言-面向对象

    2024-06-07 17:34:01       96 阅读

热门阅读

  1. 服务器创建、连接

    2024-06-07 17:34:01       22 阅读
  2. 修改hostname导致RabbitMQ数据丢失

    2024-06-07 17:34:01       25 阅读
  3. websockets怎么工作的呢?

    2024-06-07 17:34:01       27 阅读
  4. SpringBoot整合kafka

    2024-06-07 17:34:01       31 阅读
  5. vue3+element-plus 表单校验和循环form表单校验

    2024-06-07 17:34:01       26 阅读
  6. ABC318-D

    2024-06-07 17:34:01       26 阅读