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获取当前代理
- 开启代理暴露:
@Configuration @EnableAspectJAutoProxy(exposeProxy = true) public class AopConfig { // 其他配置 }
- 在方法内部获取代理对象并调用:
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
相关产品推荐
相关产品推荐

