如何检测/建议Spring Data(JPA)存储库? [英] How to instrument / advice a Spring Data (JPA) repository?
问题描述
我没有努力建议一个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屋!