如何检测/建议Spring Data(JPA)存储库? [英] How to instrument / advice a Spring Data (JPA) repository?

查看:119
本文介绍了如何检测/建议Spring Data(JPA)存储库?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我没有努力建议一个spring data jpa存储库。目标是在使用自定义注释(本例中为ResourceNotFound)注释的特定存储库中检测所有非 void 公共方法,并在返回值时抛出异常是 null 或空集合。

I'm failing in my effort to advice a spring data jpa repository. The goal is to instrument (around) all non-void public methods in a particular repository annotated with a custom annotation (ResourceNotFound in this example) and throw an exception when the return value is either null or an empty collection.

@Repository 
@ResourceNotFound
@Transactional(readOnly = true)
public interface CityRepository extends JpaRepository<City, Long>, JpaSpecificationExecutor<City> { … }

以下建议是连接用<注释的接口实现的所有公共方法code> @ResourceNotFound 。

@Pointcut("within(com.digitalmisfits.spring.aop.annotation.ResourceNotFound *)")
public void beanAnnotatedWithResourceNotFound() {}

@Pointcut("execution(public * *(..))")
public void publicMethod() {}

@Around("beanAnnotatedWithResourceNotFound() && publicMethod()")
public Object publicMethodInsideAClassMarkedWithResourceNotFound(ProceedingJoinPoint pjp) throws Throwable {

    System.out.println("publicMethodInsideAClassMarkedWithResourceNotFound " + pjp.getTarget().toString());;

    Object retVal =  pjp.proceed();

    if(((MethodSignature) pjp.getSignature()).getReturnType() != Void.TYPE && isObjectEmpty(retVal))
        throw new RuntimeException("isObjectEmpty == true");

    return retVal;
}

publicMethodInsideAClassMarkedWithResourceNotFound(...)方法在切入点指定为:

The publicMethodInsideAClassMarkedWithResourceNotFound(…) method works when the pointcut isspecified as:

@Pointcut("execution(public * package.CityRepository+.*(..))")

然而, @ResourceNotFound 注释没有被提取。这可能是由于存储库接口的基础类是(代理的) SimpleJpaRepository 而没有该特定注释的事实。

However, the @ResourceNotFound annotation is not being picked up. This might be due to the fact that the underlying class of the repository interface is a (proxied) SimpleJpaRepository which does not have that particular annotation.

有没有办法将@ResourceNotFound传播到实现?

Is there a way to propagate @ResourceNotFound to the implementation?

- 更新 -

更改了问题以反映这样的事实:建议(周围)仅适用于具有自定义注释的存储库。

Changed the question to reflect the fact that the advice (around) only should apply to repositories with a custom annotation.

推荐答案

<虽然OP严重依赖于AspectJ解决方案,但现在的问题并没有直接表明解决方案应该仅限于AspectJ。
因此,我想提供一种非AspectJ方式来建议Spring Data JPA Repository。它基于将自定义 Interceptor 添加到准系统Spring AOP代理拦截器链中。

Although the OP heavily relied on AspectJ solutions, the question as it stands doesn't directly suggest that solutions should be limited to AspectJ. Therefore I'd like to offer a non-AspectJ way to advise a Spring Data JPA Repository. It is based upon adding a custom Interceptor into barebone Spring AOP proxy interceptor chain.

首先,配置你的自定义 RepositoryFactoryBean ,例如

First, configure your custom RepositoryFactoryBean, e.g.

@Configuration
@EnableJpaRepositories(repositoryFactoryBeanClass = CustomRepositoryFactoryBean.class)
public class ConfigJpaRepositories {
}

接下来,实现 CustomRepositoryFactoryBean 添加自己的 RepositoryProxyPostProcessor JpaRepositoryFactory

Next, implement CustomRepositoryFactoryBean to add your own RepositoryProxyPostProcessor to the JpaRepositoryFactory

class CustomRepositoryFactoryBean<R extends JpaRepository<T, I>, T , I extends Serializable> extends JpaRepositoryFactoryBean<R, T, I> {

  protected RepositoryFactorySupport createRepositoryFactory(EntityManager em) {
    RepositoryFactorySupport factory = super.createRepositoryFactory(em);
    factory.addRepositoryProxyPostProcessor(new ResourceNotFoundProxyPostProcessor());
    return factory;
  }

}

您的 RepositoryProxyPostProcessor 实现应该将 MethodInterceptor 添加到特定存储库的 ProxyFactory (inspect RepositoryInformation ):

Your RepositoryProxyPostProcessor implementation should add your MethodInterceptor to the ProxyFactory for a particular Repository (inspect RepositoryInformation):

class ResourceNotFoundProxyPostProcessor implements RepositoryProxyPostProcessor {

    @Override
    public void postProcess(ProxyFactory factory, RepositoryInformation repositoryInformation) {
        if (repositoryInformation.getRepositoryInterface().equals(CityRepository.class))
            factory.addAdvice(new ResourceNotFoundMethodInterceptor());
    }

}

以及 MethodInterceptor (其中,BTW,是 org.aopalliance.aop.Advice 的子接口,所以仍然是一个建议:))你有一个完整的AspectJ的功能 @Around 建议:

and in your MethodInterceptor (which, BTW, is subinterface of org.aopalliance.aop.Advice, so still an advice :) ) you have a full power of AspectJ @Around advice:

class ResourceNotFoundMethodInterceptor implements MethodInterceptor {

    @Override
    public Object invoke(MethodInvocation invocation) throws Throwable {
        Method method = invocation.getMethod();
        ResourceNotFound resourceNotFound = method.getAnnotation(ResourceNotFound.class);
        //...
        Object result = invocation.proceed();
        //...
        return result;
    }
}   

这篇关于如何检测/建议Spring Data(JPA)存储库?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆