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

Spring AOP 学习笔记 之 常用注解

0 引入依赖

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

要在springboot中启用AOP,需要引入spring-boot-starter-aop依赖。

 

1.@EnableAspectAutoProxy

在 Spring Boot 应用中,通常通过在主配置类或启动类上添加 @EnableAspectJAutoProxy 注解来启用 @AspectJ 支持。

@Configuration
@EnableAspectJAutoProxy
public class ApplicationConfiguration {
}

@EnableAspectAutoProxy 是 Spring 框架中的一个注解,用于启用基于代理的切面(AOP)功能。以下是它的主要功能和作用:

 

  • 启用 AOP 代理

默认情况下,Spring 容器不会自动为切面创建代理对象。通过在配置类上添加 @EnableAspectAutoProxy 注解,可以显式地启用 AOP 功能。这个注解会触发 Spring 容器生成代理对象,从而支持切面拦截目标方法。

 

  • 代理模式选择

@EnableAspectAutoProxy 提供了一个属性 proxyTargetClass,用于指定代理的实现方式:
proxyTargetClass = false(默认值):使用 JDK 动态代理。
proxyTargetClass = true:使用 CGLIB 代理。
如果目标类没有实现接口,或者需要代理类本身的方法,可以选择 CGLIB 代理。

 

 

2.@Aspect

@Aspect 是 Spring AOP 中的一个核心注解,用于定义一个切面(Aspect)。

切面是 AOP 的一个模块,它封装了横切关注点(cross-cutting concerns),例如日志记录、事务管理、安全性检查等。通过使用 @Aspect 注解,你可以将这些关注点从业务逻辑中分离出来,从而使代码更加模块化和易于维护。
 

下面看一个例子:

@Slf4j
@Aspect
@Component
public class LogAspect {

    @Pointcut("execution(* com.derek.controller.*.*(..))")
    public void logSignature() {

    }

    @Before("logSignature()")
    public void logBefore(JoinPoint joinPoint) {
        log.info("before advice: {} ", joinPoint.getSignature().getName());
    }

    @Around("logSignature()")
    public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
        log.info("around into method: {}", joinPoint.getSignature().getName());
        Object result = joinPoint.proceed();
        log.info("around out method: {}", joinPoint.getSignature().getName());
        return result;
    }

    @AfterReturning(pointcut = "logSignature()", returning = "result")
    public void logReturn(JoinPoint joinPoint, Object result) {
        log.info("after returning advice: {}, result: {}", joinPoint.getSignature().getName(), result);
    }

    @AfterThrowing(pointcut = "logSignature()", throwing = "exception")
    public void logException(JoinPoint joinPoint, Exception exception) {
        log.info("after throwing advice: {}, throwing: ", joinPoint.getSignature().getName(), exception);
    }

    @After("logSignature()")
    public void logAfter(JoinPoint joinPoint) {
        log.info("after advice: {}", joinPoint.getSignature().getName());
    }

}

在LogAspect.java 文件中,@Aspect 注解用于定义一个切面类,切面类包含多个通知(Advice)和切入点(Pointcut)。

注意:定义@Aspect后,只是告诉Spring AOP要扫描该类并生成代理对象,并不会自动注入到配置容器中。所以需要在切面类上加入@Component用于将切面类声明为 Spring 管理的 Bean。
 

 

3 @Pointcut

Pointcut 是 AOP 的核心概念之一,用于定义哪些方法或代码位置需要被拦截。
通过 Pointcut 表达式,可以精确指定通知(Advice)在程序中的执行位置。
Pointcut 不直接执行任何逻辑,而是作为通知的触发条件。

定义一个切入点表达式,用于指定哪些方法会被拦截。
在例子中,@Pointcut("execution(* com.derek.controller.*.*(..))") 表示拦截 com.derek.controller 包下的所有方法。

Declaring a Pointcut :: Spring Framework

 

3.1 Pointcut 常用表达式

Pointcut 表达式是一种基于规则的语言,用于描述需要拦截的方法或类。常见的表达式包括:

 

3.2 Pointcut表达式组合

可以通过逻辑运算符(&&, ||, !)组合多个 Pointcut 表达式,实现更复杂的匹配规则。

  @Pointcut("execution(* com.example.service.*.*(..)) && args(name)")
  public void serviceMethodsWithArgs(String name) {}
  

 

3.3 Pointcut表达式性能差异

静态匹配:仅基于方法签名(如 execution 或 within),无需运行时检查,性能较好。
动态匹配:涉及运行时参数检查(如 args 或 @annotation),需要在方法执行时进行额外判断,性能较差。

// 静态匹配
@Pointcut("execution(* com.example.service.UserService.*(..))")
public void staticPointcut() {}

// 动态匹配
@Pointcut("args(java.lang.String)")
public void dynamicPointcut() {}

动态匹配增加了运行时开销,应尽量减少使用

 

4 通知(Advice)

@Before:在目标方法执行之前执行。
@After:在目标方法执行之后执行,无论是否抛出异常。
@AfterReturning:在目标方法成功返回后执行。
@AfterThrowing:在目标方法抛出异常时执行。
@Around:环绕通知,可以在目标方法执行前后插入逻辑,并且可以控制目标方法的执行。

Advice内容比较多,后面单独来一篇讲解。

 

相关文章:

  • 数据库表设计: 批次首件检验单(自定义表单)
  • Activiti(六)- 启动、挂起、激活,查询及删除流程实例
  • Why does Java‘s hashCode() in String use 31 as a multiplier?
  • AT_abc398_e [ABC398E] Tree Game 题解
  • LLM做逻辑推理题 - 三人贴纸条游戏
  • STM32 HAL实现DHT11采集温湿度
  • 大模型面经 | DeepSeek-R1中提到的思维链(Chain of Thought,CoT)是什么?
  • 如何通过Radius认证服务器实现虚拟云桌面安全登录认证:安当ASP身份认证系统解决方案
  • 鼎讯信通 便携式雷达信号模拟器:打造复杂电磁环境的“全能型选手”
  • 突破亚马逊壁垒,Web Unlocker API 助您轻松获取数据
  • 通过使用 include 语句加载并执行一个CMake脚本来引入第三方库
  • MySQL:事务隔离级别和一致性
  • 第十章 json操作
  • java实现加密解密
  • 01_JDBC
  • 集合 Collection、Map
  • Qt炫酷仪表盘
  • 计算机网络:流量控制与可靠传输机制
  • Streamlit 最新进展分析
  • C++蓝桥杯实训篇(四)
  • 直播中抢镜“甲亢哥”的翁东华卸任了!此前任文和友小龙虾公司董事
  • 海南公布知识产权保护典型案例,一企业违规申请注册“中华”商标被处罚
  • 这家企业首次签约参展进博会,为何他说“中资企业没有停止出海的步伐”
  • 广西通报桂林、贵港、玉林三市应对不力:管不住山火和露天焚烧
  • 中共中央办公厅、国务院办公厅印发《农村基层干部廉洁履行职责规定》
  • 美伊第二轮核问题间接谈判结束,伊方称“结果是建设性的”