epd*_*mer 10 java spring aspectj spring-aop spring-data-jpa
我没有努力建议一个spring data jpa存储库.目标是检测(围绕)void使用自定义注释(在此示例中为ResourceNotFound)注释的特定存储库中的所有非公共方法,并在返回值为null空集合时抛出异常.
@Repository
@ResourceNotFound
@Transactional(readOnly = true)
public interface CityRepository extends JpaRepository<City, Long>, JpaSpecificationExecutor<City> { … }
Run Code Online (Sandbox Code Playgroud)
以下建议是连接带注释的接口实现的所有公共方法@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;
}
Run Code Online (Sandbox Code Playgroud)
该publicMethodInsideAClassMarkedWithResourceNotFound(…)方法的工作原理,当切入点isspecified为:
@Pointcut("execution(public * package.CityRepository+.*(..))")
Run Code Online (Sandbox Code Playgroud)
但是,@ResourceNotFound注释没有被提取.这可能是由于存储库接口的基础类是(代理的)SimpleJpaRepository没有该特定注释的事实.
有没有办法将@ResourceNotFound传播给实现?
- 更新 -
更改了问题以反映这样的事实:建议(周围)仅适用于具有自定义注释的存储库.
如果要拦截存储库级别的存储库调用,则实际上不需要为此引入自定义注释.您应该可以使用普通类型匹配来实现此功能:
@Pointcut("execution(public !void org.springframework.data.repository.Repository+.*(..))")
Run Code Online (Sandbox Code Playgroud)
这将拦截void扩展Spring Data Repository接口的所有Spring bean 的所有非方法的执行.
可以在Spring Data示例存储库中找到一个稍微相关的示例.
尽管OP严重依赖于AspectJ解决方案,但目前的问题并不直接表明解决方案应限于AspectJ。因此,我想提供一种非AspectJ的方法来建议Spring Data JPA存储库。它基于将自定义添加Interceptor到准系统Spring AOP代理拦截器链中。
首先,配置您的自定义RepositoryFactoryBean,例如
@Configuration
@EnableJpaRepositories(repositoryFactoryBeanClass = CustomRepositoryFactoryBean.class)
public class ConfigJpaRepositories {
}
Run Code Online (Sandbox Code Playgroud)
接下来,实现CustomRepositoryFactoryBean将您自己的添加RepositoryProxyPostProcessor到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;
}
}
Run Code Online (Sandbox Code Playgroud)
您的RepositoryProxyPostProcessor实现应将您添加MethodInterceptor到ProxyFactory特定存储库(检查RepositoryInformation):
class ResourceNotFoundProxyPostProcessor implements RepositoryProxyPostProcessor {
@Override
public void postProcess(ProxyFactory factory, RepositoryInformation repositoryInformation) {
if (repositoryInformation.getRepositoryInterface().equals(CityRepository.class))
factory.addAdvice(new ResourceNotFoundMethodInterceptor());
}
}
Run Code Online (Sandbox Code Playgroud)
并且在您MethodInterceptor(BTW是的子接口org.aopalliance.aop.Advice,所以仍然是一个建议:))中,您具有AspectJ @Around建议的全部功能:
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;
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
10228 次 |
| 最近记录: |