Java Spring AOP方面与Spring数据存储库的切入点行为不一致

Java Spring AOP方面与Spring数据存储库的切入点行为不一致,java,spring,spring-data-jpa,spring-aop,spring-data-rest,Java,Spring,Spring Data Jpa,Spring Aop,Spring Data Rest,上下文 我正在使用AOP通过截取Spring数据存储库的save和delete方法为托管实体创建/删除Spring ACL记录。我的所有存储库都是@RepositoryRestResource带注释的接口,扩展分页和排序存储库或crudepository。这在过去一直运作良好。不幸的是,我无法准确地确定它停止工作的时间点(或代码更改) 预期行为 以下建议适用于所有保存方法 @Pointcut("execution(* org.springframework.data.repository.*.s

上下文

我正在使用AOP通过截取Spring数据存储库的save和delete方法为托管实体创建/删除Spring ACL记录。我的所有存储库都是
@RepositoryRestResource
带注释的接口,扩展
分页和排序存储库
crudepository
。这在过去一直运作良好。不幸的是,我无法准确地确定它停止工作的时间点(或代码更改)

预期行为

以下建议适用于所有保存方法

@Pointcut("execution(* org.springframework.data.repository.*.save(*))")
public void defaultRepoSave() {}

// may be useful for overridden methods
@Pointcut("execution(* com.xxx.yyy.repository.*.save(..))")
public static void customRepoSave() {}

@Pointcut("defaultRepoSave() || customRepoSave()")
public static void repoSave() {}

@Around(value="repoSave() && args(entity)", argNames="entity")
public Object aroundSave(ProceedingJoinPoint pjp, Object entity) throws Throwable{
    log.info("Saving ...");
    return pjp.proceed();
}
注意:我尝试了
@enableSpectJautoproxy(exposeProxy=true/false,proxyTargetClass=true/false)
的各种组合,但它似乎对这个特定的建议没有任何影响

问题

该建议针对某些存储库,而不是其他存储库。两个存储库位于同一个包中。调试表明这两个存储库都是代理的,但左侧存储库的执行完全缺少与通知相关的拦截器。右边的那个按预期进行

为了消除切入点不匹配的可能性,我创建了一个自定义注释,并将其添加到两个存储库中的.save()方法中

注释:

@Retention(RUNTIME)
@Target(METHOD)
public @interface AclManaged {}
用作:

@Override
@AclManaged
Entity1 save(Entity1 entity); 
建议如下:

@Around("@annotation(aclManaged)")
public Object aclManaged(ProceedingJoinPoint joinPoint, AclManaged aclManaged) throws Throwable {
    log.info("Acl managed");
    return joinPoint.proceed();
}
相同的故事-注释在一个存储库中工作,但对于
执行(…save…)
切入点失败的存储库不会触发

出于测试目的,我通过从Postman向每个相应的存储库rest端点发布一个空实体来调用这两个方法。但是,当直接从我的代码调用存储库时,同样的问题也会发生

存储库为完整性而编码(即使是最基本的回购实现,也会出现不一致的行为):

---编辑:我将存储库简化到最低限度--

@RepositoryRestResource(collectionResourceRel=“entity1s”,path=“entity1s”)
公共接口Entity1Repository扩展了分页和排序存储库{
//这是应该激发两个不同建议的方法
@凌驾
@ACL管理
Entity1保存(Entity1实体);
}
@RepositoryRestResource(collectionResourceRel=“entity2s”,path=“entity2s”)
公共接口Entity2Repository扩展了分页和排序存储库{
//这两个方面完全吻合
@凌驾
@ACL管理
Entity2保存(Entity2 ics);
}
问题

什么会阻碍AOP方面?Spring如何填充调用拦截器链

解决AOP方面故障的最佳方法是什么?(假设执行和注释切入点都失败)

另一个稍微不同的注意事项是,建议使用JPA审计来管理ACL而不是AOP吗

版本


spring 5.0.8.RELEASE、spring data rest 3.0.9.RELEASE、spring data jpa 2.0.9.RELEASE(全部由spring Boot 2.0.4管理)

该问题似乎是由spring Booot的
@Enable…
注释和my
@Configuration
类的不幸组合引起的。该框架似乎有几种不同的方法来确定类/接口代理(源于
@EnableCaching
@EnableTransactionManagement
@enablespectjautoproxy
@enablesync
)。在某些情况下,它们似乎劫持了预期的行为。我能够通过以下方式恢复预期行为:

  • proxyTargetClass=true
    添加到所有
    @Enable..
    注释
  • @Enable…
    注释移动到相关的
    @Configuration
我无法确定是哪种组合导致了不一致的行为,即我没有最小的可复制测试用例

对于不一致的MethodInvocationInterceptor链背后的根本原因,我仍然对更深入的见解感兴趣