You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Spring注解式AOP除首个切入点外Advice执行两次问题求助

解决Spring注解AOP通知执行两次的问题

看起来你遇到的核心问题是切面通知被重复执行,这在纯注解AOP配置里最常见的原因是切面类被Spring容器重复注册了,我来帮你一步步排查和解决:

一、排查核心原因:切面实例重复创建

你现在的配置是:

  • LoggingConfig里用@Bean手动创建了PreProcessLogs实例
  • PreProcessLogs本身标注了@Aspect

如果你的项目开启了组件扫描(比如用了@SpringBootApplication或者@ComponentScan),且PreProcessLogs所在的包被扫描到,那么Spring会做两件事:

  1. 因为@Aspect+组件扫描,自动把PreProcessLogs注册为Bean
  2. 因为LoggingConfig里的@Bean,又手动创建了一个PreProcessLogs实例

这就导致容器里存在两个切面实例,每个实例都会触发对应的通知,自然就执行两次了。

你可以快速验证:在PreProcessLogs的构造函数里加一行日志,启动应用时如果日志打印两次,就确认是这个问题。

二、两种解决方案

方案1:用组件扫描管理切面(推荐)

去掉LoggingConfig里的@Bean声明,给切面类加上@Component注解,让Spring通过组件扫描自动注册:

修改切面类:

@Aspect
@Component // 加上这个注解
public class PreProcessLogs {
    // 你的@Before、@After等通知方法
    @Before("your-pointcut-expression")
    public void beforeAdvice(JoinPoint joinPoint) {
        // 你的逻辑
    }
}

简化配置类:

@Configuration
@EnableAspectJAutoProxy
// 如果切面不在当前配置类的包及其子包下,需要加上@ComponentScan指定切面所在包
// @ComponentScan(basePackages = "com.yourpackage.aspect")
public class LoggingConfig {
    // 移除@Bean PreProcessLogs的代码
}

方案2:仅通过@Bean注册切面

如果不想用@Component,那要确保切面类不会被组件扫描到:

  1. PreProcessLogs放到组件扫描范围外的包
  2. 或者在@ComponentScan里排除这个类
  3. 保留LoggingConfig里的@Bean声明,确保只有这一个切面实例

三、其他可能的排查方向

如果上面的方法没解决,再检查这两个点:

  • 切入点表达式是否重叠:比如多个切入点表达式匹配了同一个方法,导致多次触发。可以把每个切入点的表达式缩小范围,比如指定具体的包、类或方法名
  • @EnableAspectJAutoProxy是否重复配置:如果多个@Configuration类都加了@EnableAspectJAutoProxy,虽然不会重复注册代理创建器,但如果结合其他配置可能有影响,建议只在一个配置类里加这个注解

内容的提问来源于stack exchange,提问作者Naz Haque

火山引擎 最新活动