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 替换为您的子类。

或者,只需将您的建议添加到容器工厂的建议链中,所有听众都会收到建议。然后您可以进行运行时检查以查看是否存在其他注释。