2016-10-13 2 views
0

Gibt es eine Möglichkeit zum Abfangen von Aufrufen von Bean-Methoden, die mit @RabbitListener kommentiert wurden, ohne AspectJ zu verwenden.Spring Rabbit: Intercept-Methodenaufrufe mit @RabbitListener ohne AspectJ-Verwendung kommentiert

Der Code ist so etwas wie dieses

@OtherAnnotation 
@RabbitListener 
public void do(Message message) 

Ich brauche alle Anrufe @RabbitListener Methode abfangen, wenn die Methode @OtherAnnotation Annotation hat.

UPDATE:

Ich konnte es Lösung mit Gary Russell zu arbeiten.

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); 
     } 
    } 
} 

Die Bohne Definition ist wie:

@Bean(name = RabbitListenerConfigUtils.RABBIT_LISTENER_ANNOTATION_PROCESSOR_BEAN_NAME) 
    public CustomRabbitListenerAnnotationBeanPostProcessor customRabbitListenerAnnotationBeanPostProcessor() { 
     return new CustomRabbitListenerAnnotationBeanPostProcessor(); 
    } 

Es ist ein bisschen hässlich, aber es funktioniert. Wenn jemand eine bessere Lösung hat, teilen Sie es bitte mit.

Antwort

1

experimentieren können Sie RabbitListenerAnnotationBeanPostProcessor Unterklasse und überschreiben die processListener Methode und ändern Sie die Bean, bevor Sie die Super-Version aufrufen.

Dann ersetzen Sie die RabbitListenerConfigUtils.RABBIT_LISTENER_ANNOTATION_PROCESSOR_BEAN_NAME Bean von der @EnableRabbit mit Ihrer Unterklasse registriert.

Oder geben Sie einfach Ihre Ratschläge an die Beratungsstelle der Containerfabrik und alle Zuhörer werden benachrichtigt. Sie können dann eine Laufzeitprüfung durchführen, um festzustellen, ob die andere Anmerkung vorhanden ist.

+0

kann es nicht zur Advice-Kette hinzufügen, da der Pointcut für die Advice-Chain auf der Methode 'public abstract void org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer $ ContainerDelegate.invokeListener' und nicht auf der mit '@ RabitListener' gekennzeichneten Methode liegt – lolotron

+0

Ja, natürlich, tut mir leid - dieser Hinweis wird ausgeführt, bevor die Nachricht konvertiert wird. –

+0

Ich aktualisierte meine Frage mit der Lösung mit Ihrer ersten Annäherung.Es ist ein bisschen hässlich, aber es funktioniert. Danke vielmals! – lolotron

1

denke ich, was Sie suchen für ein bean-post-processor

ist

herer ein einfaches Beispiel: https://www.tutorialspoint.com/spring/spring_bean_post_processors.htm

, wenn Sie Anrufe müssen abfangen Sie einen Proxy über die zurückgegebene Instanz wickeln können. Ein gutes Beispiel ist org.springframework.validation.beanvalidation.MethodValidationPostProcessor. Sie können wahrscheinlich auch org.springframework.aop.framework.AbstractAdvisingBeanPostProcessor erweitern.


EDIT ich lerne mich gerade dies so hoffe ich, dass der richtige Weg, dies zu tun, aber das ist für mich gearbeitet, wenn sie mit ihm

@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(); 
      } 
     }; 
    } 
} 
+0

Das sieht nach einem guten Ansatz aus, aber eine mit @RabitListener annotierte Methode wird von SimpleMessageListenerContainer mit AOP-Proxy aufgerufen. Aus diesem Grund werden andere Anmerkungen zur Methode ignoriert. – lolotron

+0

Ihr Code funktioniert gut, wenn er auf einer Spring-Bean verwendet wird Wenn es mit RabitListener/SimpleMessageListenerContainer verwendet wird, funktioniert es nicht. Sie können es selbst ausprobieren. Erstellen Sie eine Konfiguration mit '@ EnableRabbit', einer Bean mit einer Methode, die sowohl mit @ RabbitListener als auch mit @ YourCustomAnnotation versehen ist, und senden Sie eine Nachricht an diesen RabbitListener. Der Interceptor für '@ YourCustomAnnotaion' wird nicht ausgeführt. Danke trotzdem für deine Hilfe. – lolotron

Verwandte Themen