Java Spring AOP方面与Spring数据存储库的切入点行为不一致
上下文 我正在使用AOP通过截取Spring数据存储库的save和delete方法为托管实体创建/删除Spring ACL记录。我的所有存储库都是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
@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