SpringBoot AOP @Pointcut切入点execution表达式排除类中的具体方法

本文详细介绍了如何在SpringBoot的AOP中使用@Pointcut切入点表达式来排除特定类或方法。通过示例展示了如何定义公共切入点、排除切入点及组合使用,实现对Controller层方法的精细化拦截,并给出了实际代码示例。文章旨在帮助读者更好地理解和应用SpringBoot AOP的切入点排除功能。

背景

工作中遇到了,要针对在原有的切面范围基础之上,排除掉某些类中的方法。所以本篇文章主要介绍了SpringBoot AOP @Pointcut切入点表达式排除某些类中的方法的方式。 

 

  • 修饰符匹配(modifier-pattern?)
  • 返回值匹配(ret-type-pattern)可以为*表示任何返回值,全路径的类名等
  • 类路径匹配(declaring-type-pattern?)
  • 方法名匹配(name-pattern)可以指定方法名 或者 *代表所有, set* 代表以set开头的所有方法
  • 参数匹配((param-pattern))可以指定具体的参数类型,多个参数间用“,”隔开,各个参数也可以用“*”来表示匹配任意类型的参数,如(String)表示匹配一个String参数的方法;(*,String) 表示匹配有两个参数的方法,第一个参数可以是任意类型,而第二个参数是String类型;可以用(..)表示零个或多个任意参数
  • 异常类型匹配(throws-pattern?)
  • 其中后面跟着“?”的是可选项

@Pointcut切入点排除某一些类或者方法不进行拦截

示例

@Pointcut("execution(public com.lingyejun.bolg.dto.Result com.lingyejun.blog.web..*Controller.*(..))")
public void normalPointcutWeb() {
}
 
@Pointcut("execution(public com.lingyejun.bolg.dto.Result  com.lingyejun.blog.web.book.controller.SafeBabyController.getBabyBirth(..))")
public void excludePointcutWeb() {
}
 
@Pointcut("normalPointcutWeb() && !excludePointcutWeb()")
public void allPointcutWeb() {
}
 
@Before("allPointcutWeb()")
public void startLog(JoinPoint joinPoint) {
    String className = joinPoint.getSignature().getDeclaringType().getSimpleName();
    String methodName = joinPoint.getSignature().getName();
    logger.info("{}.{} start", className, methodName);
}

normalPointcutWeb:切入点为——以public修饰的方法、方法的返回值为com.lingyejun.bolg.dto.Result、类路径为com.lingyejun.blog.web下的所有以Controller结尾的类、携带有任意个参数的切入点。

excludePointcutWeb:切入点为——以public修饰的方法、方法的返回值为com.lingyejun.bolg.dto.Result、类路径为com.lingyejun.blog.web.book.controller.SafeBabyController、方法名为getBabyBirth、携带任意个参数的切入点。

allPointcutWeb:切入点为满足normalPointcutWeb且不满足excludePointcutWeb的切入点的范围

本篇文章如有帮助到您,请给「翎野君」点个赞,感谢您的支持。

原文链接:https://www.cnblogs.com/lingyejun/p/16564440.html

<think> 首先,用户的问题是:“我想了解Spring AOP@Pointcut的相关信息,可能包括使用方法、原理、示例等 请问Spring AOP@Pointcut的使用方法和原理”。用户要求我参考提供的引用内容,这些引用是关于Spring AOP@Pointcut的。 引用内容: - 引用[1]:讨论了@Pointcut注解在Spring Boot AOP中的作用,允许定义切点并应用通知。 - 引用[2]:描述了使用"bean(...)"匹配Spring bean的方法调用。 - 引用[3]:提到定义Pointcut后,在通知中使用它。 - 引用[4]:介绍了AspectJ框架与Spring AOP的集成,以及定义切入点的步骤。 - 引用[5]:提供了@Pointcut注解的细节,包括value和argNames选项。 我的回答需要: - 使用中文回答。 - 结构清晰,帮助用户逐步解决问题。 - 确保回答真实可靠。 - 对于行内数学表达式,使用$...$格式;对于独立公式,使用$$...$$格式并单独成段。但在这个主题中,可能没有数学表达式,所以我可以忽略这一点。 - 生成相关问题。 - 在回答中引用的段落末尾自然地添加引用标识,如[^1]。 回答结构: 1. **引言**:简要介绍@Pointcut的作用和重要性。 2. **使用方法**:解释如何定义和使用@Pointcut,包括语法和示例。 3. **原理**:解释@Pointcut的工作原理,基于AOP概念。 4. **示例**:提供代码示例来演示@Pointcut。 5. **总结**:重申关键点。 6. **相关问题**:生成相关问题。 使用引用: - 我需要自然地融入引用内容。例如: - 引用[1]提到@Pointcut用于定义切点和应用通知。 - 引用[2]说明如何使用"bean(...)"匹配。 - 引用[3]展示在通知中使用Pointcut。 - 引用[4]讨论AspectJ与Spring AOP的集成。 - 引用[5]给出@Pointcut注解的选项。 确保回答可靠: - 基于我对Spring AOP的知识,结合引用内容。 - Spring AOP基于代理机制,使用AspectJ的切点表达式。 最终输出: - 回答主体。 - 相关问题列表。 相关问题生成: - 基于主题,生成3-5个相关问题,如优化、常见错误、高级用法等。 - 格式如示例所示:§§相关问题§§ 然后列出问题。 </think>### Spring AOP@Pointcut的使用方法和原理 在Spring AOP(面向切面编程)中,`@Pointcut`注解用于定义切点(Pointcut),即指定在哪些方法或位置应用通知(Advice)。切点是AOP的核心,它允许开发者声明式地定义横切关注点(如日志、事务管理),从而实现代码的解耦和重用[^1]。下面我将逐步解释其使用方法、原理,并提供示例。 #### 1. **@Pointcut的使用方法** `@Pointcut`的使用主要包括定义切点表达式和在通知中引用它。切点表达式使用AspectJ语法,Spring AOP基于此语法实现匹配。 - **基本语法**: - 使用`@Pointcut`注解定义一个方法(通常为空方法),其`value`属性指定切点表达式。 - 表达式可以匹配方法调用、、参数等。例如: - `execution(* com.example.service.*.*(..))`:匹配`com.example.service`包下所有的所有方法。 - `bean(userService)`:匹配Spring容器中ID为`userService`的bean的所有方法调用(基于引用[2]的解释)[^2]。 - 切点方法在Aspect中定义,并使用`@Aspect`标注该。 - **定义和引用步骤**: 1. **创建Aspect**:使用`@Aspect`标注一个,并在其中定义`@Pointcut`。 2. **定义切点**:编写一个空方法,添加`@Pointcut`注解。 3. **应用通知**:在通知(如`@Before`、`@After`)中引用该切点(引用[3]中的示例)[^3]。 - **代码示例**: 假设我们有一个服务`UserService`,需要记录其所有方法的执行日志。 ```java import org.aspectj.lang.annotation.*; import org.springframework.stereotype.Component; @Aspect @Component public class LoggingAspect { // 定义切点:匹配UserService的所有方法 @Pointcut("bean(userService)") // 基于引用[2],使用bean表达式匹配特定bean public void userServicePointcut() {} // 在通知中引用切点 @Before("userServicePointcut()") // 方法执行前应用通知 public void logBefore() { System.out.println("方法开始执行..."); } } ``` 在这个示例中: - `@Pointcut("bean(userService)")`定义了切点,匹配`userService` bean的所有方法。 - `@Before`通知引用了该切点,在方法执行前打印日志。 - **高级用法**: - **参数匹配**:使用`argNames`属性指定参数名(引用[5]),例如`@Pointcut(value = "execution(* save(..)) && args(user)", argNames = "user")`匹配`save`方法并捕获`user`参数[^5]。 - **组合表达式**:使用`&&`、`||`组合多个切点,提升灵活性。 - **集成AspectJ**:Spring AOP可以与AspectJ框架集成(引用[4]),支持更强大的切点定义,如基于注解的匹配(如`@annotation(org.springframework.transaction.annotation.Transactional)`)[^4]。 #### 2. **@Pointcut的原理** `@Pointcut`的工作原理基于Spring AOP的代理机制和AspectJ的切点模型,核心是运行时动态生成代理对象。 - **代理机制**: - Spring AOP通过JDK动态代理或CGLIB代理创建目标对象的代理。当方法被调用时,代理拦截调用,并根据切点表达式决定是否应用通知。例如,如果切点匹配方法,则执行相关通知(如`@Before`)[^1]。 - 这个过程在Spring容器初始化时完成:Spring扫描`@Aspect`,解析`@Pointcut`定义,并生成代理bean(引用[4]中的步骤)[^4]。 - **切点表达式解析**: - 切点表达式在编译或运行时被解析为匹配规则。例如,`execution(* *.*(..))`会被转换为字节码级别的匹配逻辑。 - 匹配基于方法签名:包括名、方法名、参数型和返回型。Spring使用AspectJ weaver(编织器)在运行时应用这些规则(AspectJ提供底层支持)[^4][^5]。 - **性能考虑**: - 切点表达式的复杂度影响性能。简单表达式(如`bean(...)`)高效,而复杂表达式(涉及通配符或参数匹配)可能增加运行时开销。优化时,应优先使用具体匹配减少扫描范围[^2][^5]。 - **与AspectJ的关系**: - Spring AOP是AspectJ的子集,专注于方法级别的切面(引用[4])。AspectJ提供更全面的AOP功能(如构造函数切点),但Spring AOP通过集成简化了使用。原理上,`@Pointcut`注解最终由AspectJ引擎处理[^4][^5]。 #### 3. **实际应用建议** - **最佳实践**: - 将切点定义在单独方法中,便于重用(如示例中的`userServicePointcut()`)。 - 测试切点时,使用单元测试验证匹配准确性。 - 避免过度使用复杂表达式,以保持性能。 - **常见问题**: - 如果切点不生效,检查表达式是否正确或Spring配置是否启用AOP(如添加`@EnableAspectJAutoProxy`)。 - 参数匹配错误时,确保`argNames`与通知方法参数一致(引用[5])[^5]。 总结来说,`@Pointcut`是Spring AOP实现横切关注点的关键工具,它通过声明式表达式定义应用通知的位置,提升代码模块化[^1]。结合AspectJ的强大功能,开发者可以高效地处理日志、安全等通用逻辑[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值