You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot中@Around切面仅生效于@RestController,不生效于@Service

问题分析与解决:AspectJ切面无法拦截@Service内部方法调用

核心原因

你当前使用的@EnableAspectJAutoProxy启用的是Spring AOP,而非原生AspectJ。Spring AOP基于动态代理(JDK动态代理或CGLIB)实现,只有通过代理对象调用方法时才会触发切面逻辑:

  • @RestController的方法是由外部(Spring MVC的DispatcherServlet)通过代理对象发起调用,因此切面能正常触发;
  • 当你在@Service的doTest()方法内部直接调用thisMethodShouldNotBeCalled()时,this指向的是原始服务对象,而非Spring生成的代理对象,自然不会触发切面拦截。

解决方案

方案1:注入自身代理对象调用

在@Service类中注入自身的代理实例,通过代理对象触发目标方法:

@Service
public class YourService {
    @Autowired
    private YourService selfProxy;

    public void doTest() {
        // 通过代理对象调用,触发切面校验
        selfProxy.thisMethodShouldNotBeCalled();
    }

    @RequiresEntitlementsAnyOf
    public void thisMethodShouldNotBeCalled() {
        // 业务逻辑
    }
}
  • 若服务类实现了接口,默认使用JDK动态代理,需确保注入的是接口类型;
  • 若想强制使用CGLIB代理(支持类类型注入),可修改配置:@EnableAspectJAutoProxy(proxyTargetClass = true)

方案2:通过AopContext获取当前代理

  1. 开启代理暴露:
@Configuration
@EnableAspectJAutoProxy(exposeProxy = true)
public class AopConfig {
    // 其他配置
}
  1. 在方法内部获取代理对象并调用:
public void doTest() {
    ((YourService) AopContext.currentProxy()).thisMethodShouldNotBeCalled();
}

方案3:切换为原生AspectJ织入

如果需要彻底摆脱Spring动态代理的限制(实现所有方法调用的拦截,包括内部调用),可以使用原生AspectJ:

  • 添加AspectJ依赖(aspectjrt、aspectjweaver);
  • 选择编译时织入(通过Maven/Gradle插件在编译阶段处理类文件)或加载时织入(通过JVM参数指定javaagent:aspectjweaver.jar);
  • 此时无需依赖Spring AOP的动态代理机制,所有方法调用都会被切面拦截。

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 08:07:44