Spring rabbit:在没有使用 AspectJ 的情况下使用 @RabbitListener 注释的拦截方法调用
Spring rabbit: Intercept method calls annotated with @RabbitListener without AspectJ usage
有没有办法在不使用 AspectJ 的情况下拦截使用 @RabbitListener 注释的 bean 方法的调用。
代码是这样的
@OtherAnnotation
@RabbitListener
public void do(Message message)
我需要拦截对@RabbitListener 方法的所有调用,如果该方法具有@OtherAnnotation 注释。
更新:
我设法使用 Gary Russell 解决方案使其工作。
public class CustomRabbitListenerAnnotationBeanPostProcessor extends RabbitListenerAnnotationBeanPostProcessor {
@Override
protected void processAmqpListener(RabbitListener rabbitListener, final Method method, Object bean, String beanName) {
if (method.isAnnotationPresent(OtherAnnotation.class)) {
ProxyFactory proxyFactory = new ProxyFactory(bean);
proxyFactory.addAdvisor(new StaticMethodMatcherPointcutAdvisor(new OtherAnnotationInterceptor()) {
@Override
public boolean matches(Method advisorMethod, Class<?> targetClass) {
return advisorMethod.equals(method);
}
});
Object proxiedBean = proxyFactory.getProxy();
super.processAmqpListener(rabbitListener, method, proxiedBean, beanName);
} else {
super.processAmqpListener(rabbitListener, method, bean, beanName);
}
}
}
bean 定义如下:
@Bean(name = RabbitListenerConfigUtils.RABBIT_LISTENER_ANNOTATION_PROCESSOR_BEAN_NAME)
public CustomRabbitListenerAnnotationBeanPostProcessor customRabbitListenerAnnotationBeanPostProcessor() {
return new CustomRabbitListenerAnnotationBeanPostProcessor();
}
它有点难看,但它确实有效。如果谁有更好的解决方案,请分享。
我想你要找的是 bean-post-processor
这是一个简单的例子:
https://www.tutorialspoint.com/spring/spring_bean_post_processors.htm
如果您需要拦截调用,您可以在返回的实例上包装一个代理。一个很好的例子是 org.springframework.validation.beanvalidation.MethodValidationPostProcessor。您也可以扩展 org.springframework.aop.framework.AbstractAdvisingBeanPostProcessor 。
编辑我只是自己学习,所以我希望这是正确的方法,但这在我试验时对我有用
@Component
public class MyInterceptAnnotationBeanPostProcessor
extends AbstractBeanFactoryAwareAdvisingPostProcessor
implements InitializingBean {
public void afterPropertiesSet() {
AnnotationMatchingPointcut pointcut = new AnnotationMatchingPointcut(
null,
MyIntercept.class);
this.advisor = new DefaultPointcutAdvisor(pointcut, this.createAdvice());
}
protected Advice createAdvice() {
return new MethodInterceptor() {
@Override
public Object invoke(MethodInvocation arg0) throws Throwable {
System.out.println("advice");
return arg0.proceed();
}
};
}
}
您可以子类化 RabbitListenerAnnotationBeanPostProcessor
并覆盖 processListener
方法并在调用超级版本之前修改 bean。
然后,将 @EnableRabbit
注册的 RabbitListenerConfigUtils.RABBIT_LISTENER_ANNOTATION_PROCESSOR_BEAN_NAME
bean 替换为您的子类。
或者,只需将您的建议添加到容器工厂的建议链中,所有听众都会收到建议。然后您可以进行运行时检查以查看是否存在其他注释。
有没有办法在不使用 AspectJ 的情况下拦截使用 @RabbitListener 注释的 bean 方法的调用。
代码是这样的
@OtherAnnotation
@RabbitListener
public void do(Message message)
我需要拦截对@RabbitListener 方法的所有调用,如果该方法具有@OtherAnnotation 注释。
更新:
我设法使用 Gary Russell 解决方案使其工作。
public class CustomRabbitListenerAnnotationBeanPostProcessor extends RabbitListenerAnnotationBeanPostProcessor {
@Override
protected void processAmqpListener(RabbitListener rabbitListener, final Method method, Object bean, String beanName) {
if (method.isAnnotationPresent(OtherAnnotation.class)) {
ProxyFactory proxyFactory = new ProxyFactory(bean);
proxyFactory.addAdvisor(new StaticMethodMatcherPointcutAdvisor(new OtherAnnotationInterceptor()) {
@Override
public boolean matches(Method advisorMethod, Class<?> targetClass) {
return advisorMethod.equals(method);
}
});
Object proxiedBean = proxyFactory.getProxy();
super.processAmqpListener(rabbitListener, method, proxiedBean, beanName);
} else {
super.processAmqpListener(rabbitListener, method, bean, beanName);
}
}
}
bean 定义如下:
@Bean(name = RabbitListenerConfigUtils.RABBIT_LISTENER_ANNOTATION_PROCESSOR_BEAN_NAME)
public CustomRabbitListenerAnnotationBeanPostProcessor customRabbitListenerAnnotationBeanPostProcessor() {
return new CustomRabbitListenerAnnotationBeanPostProcessor();
}
它有点难看,但它确实有效。如果谁有更好的解决方案,请分享。
我想你要找的是 bean-post-processor
这是一个简单的例子: https://www.tutorialspoint.com/spring/spring_bean_post_processors.htm
如果您需要拦截调用,您可以在返回的实例上包装一个代理。一个很好的例子是 org.springframework.validation.beanvalidation.MethodValidationPostProcessor。您也可以扩展 org.springframework.aop.framework.AbstractAdvisingBeanPostProcessor 。
编辑我只是自己学习,所以我希望这是正确的方法,但这在我试验时对我有用
@Component
public class MyInterceptAnnotationBeanPostProcessor
extends AbstractBeanFactoryAwareAdvisingPostProcessor
implements InitializingBean {
public void afterPropertiesSet() {
AnnotationMatchingPointcut pointcut = new AnnotationMatchingPointcut(
null,
MyIntercept.class);
this.advisor = new DefaultPointcutAdvisor(pointcut, this.createAdvice());
}
protected Advice createAdvice() {
return new MethodInterceptor() {
@Override
public Object invoke(MethodInvocation arg0) throws Throwable {
System.out.println("advice");
return arg0.proceed();
}
};
}
}
您可以子类化 RabbitListenerAnnotationBeanPostProcessor
并覆盖 processListener
方法并在调用超级版本之前修改 bean。
然后,将 @EnableRabbit
注册的 RabbitListenerConfigUtils.RABBIT_LISTENER_ANNOTATION_PROCESSOR_BEAN_NAME
bean 替换为您的子类。
或者,只需将您的建议添加到容器工厂的建议链中,所有听众都会收到建议。然后您可以进行运行时检查以查看是否存在其他注释。