Spring rabbit:使用@RabbitListener注释的Intercept方法调用没有使用AspectJ

时间:2016-10-13 10:42:55

标签: spring spring-amqp spring-rabbit spring-rabbitmq

是否可以在不使用AspectJ的情况下拦截使用@RabbitListener注释的bean方法的调用。

代码是这样的

@OtherAnnotation
@RabbitListener
public void do(Message message)

如果方法有@OtherAnnotation注释,我需要拦截对@RabbitListener方法的所有调用。

更新

我设法使用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();
    }

它有点难看,但它确实有效。如果有人有更好的解决方案,请分享。

2 个答案:

答案 0 :(得分:1)

我认为你要找的是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();
            }
        };
    }
}

答案 1 :(得分:1)

您可以继承RabbitListenerAnnotationBeanPostProcessor并覆盖processListener方法并在调用超级版本之前修改bean。

然后,用您的子类替换RabbitListenerConfigUtils.RABBIT_LISTENER_ANNOTATION_PROCESSOR_BEAN_NAME注册的@EnableRabbit bean。

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