Spring AOP匹配@Query注解方法报错:createQuery()未被调用
问题分析与修复方案
核心错误点
- 切入点表达式错误:你使用
@within(org.springframework.data.jpa.repository.Query),但@within是匹配类上标注目标注解的类中所有方法,而@Query是标注在方法上的,应改用@annotation(org.springframework.data.jpa.repository.Query)。另外你自定义了@MyFilter注解,若要增强标注该注解的Repository方法,切入点需匹配@annotation(你的包名.MyFilter)。 - 切面方法参数与返回值错误:
@Around通知必须用ProceedingJoinPoint作为参数(而非JointPoint),且需调用proceed()执行原方法并返回结果(返回值应为Object而非void),否则原Repository方法不会执行,AOP逻辑也无法正常触发。 - 切入点访问修饰符问题:private切入点虽可在切面内部使用,但建议改为public,避免潜在访问性问题。
修复后的代码示例
1. 修正后的MyFilter切面类
@Aspect @Component public class MyFilter { // 切入点:匹配标注了@MyFilter的方法 @Pointcut("execution(* *(..)) && @annotation(com.yourpackage.MyFilter)") public void myFilterMethod() {} // 若要直接增强所有带@Query的Repository方法,可使用这个切入点 // @Pointcut("execution(* com.yourpackage.repository..*(..)) && @annotation(org.springframework.data.jpa.repository.Query)") // public void queryMethod() {} @Around("myFilterMethod()") public Object invoke(ProceedingJoinPoint pjp) throws Throwable { // 获取方法上的@Query注解,修改value值 MethodSignature signature = (MethodSignature) pjp.getSignature(); Method method = signature.getMethod(); Query queryAnnotation = method.getAnnotation(Query.class); if (queryAnnotation != null) { // 通过反射修改注解的value值(注解默认不可变,需突破访问限制) Field valueField = Query.class.getDeclaredField("value"); valueField.setAccessible(true); valueField.set(queryAnnotation, "你的修改后的SQL语句"); } // 执行原方法并返回结果 return pjp.proceed(); } }
2. 额外注意事项
- 注解不可变性:JVM中注解实例默认不可变,反射修改属性需谨慎,可能存在兼容性问题。更规范的JPA扩展方式是通过自定义
RepositoryFactoryBean来修改查询语句。 - Spring AOP生效条件:确保Repository接口所在包被Spring扫描到,且已启用
@EnableAspectJAutoProxy使AOP配置生效。 - 切入点范围限制:建议在切入点中限定Repository的包路径(如
execution(* com.yourpackage.repository..*(..))),避免增强不必要的方法。
内容的提问来源于stack exchange,提问作者bhargavaravalik
相关产品推荐
相关产品推荐

