@Target(value=TYPE) @Retention(value=RUNTIME) @Documented @Import(value=RabbitListenerConfigurationSelector.class) public @interface EnableRabbit
RabbitListenerContainerFactory
. To be used on
Configuration
classes as follows:
@Configuration @EnableRabbit public class AppConfig { @Bean public SimpleRabbitListenerContainerFactory myRabbitListenerContainerFactory() { SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory(); factory.setConnectionFactory(connectionFactory()); factory.setMaxConcurrentConsumers(5); return factory; } // other @Bean definitions }The
RabbitListenerContainerFactory
is responsible to create the listener container
responsible for a particular endpoint. Typical implementations, as the
SimpleRabbitListenerContainerFactory
used in the sample above, provides the necessary configuration options that are supported by
the underlying MessageListenerContainer
.
@EnableRabbit
enables detection of RabbitListener
annotations on any
Spring-managed bean in the container. For example, given a class MyService
:
package com.acme.foo; public class MyService { @RabbitListener(containerFactory="myRabbitListenerContainerFactory", queues="myQueue") public void process(String msg) { // process incoming message } }The container factory to use is identified by the
containerFactory
attribute defining the name of the RabbitListenerContainerFactory
bean to use. When none
is set a RabbitListenerContainerFactory
bean with name rabbitListenerContainerFactory
is
assumed to be present.
the following configuration would ensure that every time a Message
is received on the Queue
named "myQueue", MyService.process()
is called with the content of the message:
@Configuration @EnableRabbit public class AppConfig { @Bean public MyService myService() { return new MyService(); } // Rabbit infrastructure setup }Alternatively, if
MyService
were annotated with @Component
, the
following configuration would ensure that its @RabbitListener
annotated
method is invoked with a matching incoming message:
@Configuration @EnableRabbit @ComponentScan(basePackages="com.acme.foo") public class AppConfig { }Note that the created containers are not registered against the application context but can be easily located for management purposes using the
RabbitListenerEndpointRegistry
.
Annotated methods can use flexible signature; in particular, it is possible to use
the Message
abstraction and related annotations,
see RabbitListener
Javadoc for more details. For instance, the following would
inject the content of the message and a a custom "myCounter" AMQP header:
@RabbitListener(containerFactory = "myRabbitListenerContainerFactory", queues = "myQueue") public void process(String msg, @Header("myCounter") int counter) { // process incoming message }These features are abstracted by the
MessageHandlerMethodFactory
that is responsible to build the necessary invoker to process
the annotated method. By default,
DefaultMessageHandlerMethodFactory
is used.
When more control is desired, a @Configuration
class may implement
RabbitListenerConfigurer
. This allows access to the underlying
RabbitListenerEndpointRegistrar
instance. The following example demonstrates how to specify an explicit default
RabbitListenerContainerFactory
@Configuration @EnableRabbit public class AppConfig implements RabbitListenerConfigurer { @Override public void configureRabbitListeners(RabbitListenerEndpointRegistrar registrar) { registrar.setContainerFactory(myRabbitListenerContainerFactory()); } @Bean public RabbitListenerContainerFactory<?> myRabbitListenerContainerFactory() { // factory settings } @Bean public MyService myService() { return new MyService(); } }For reference, the example above can be compared to the following Spring XML configuration:
<beans>
<rabbit:annotation-driven container-factory="myRabbitListenerContainerFactory"/>
<bean id="myRabbitListenerContainerFactory"
class="org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory">
// factory settings
</bean>
<bean id="myService" class="com.acme.foo.MyService"/>
</beans>
It is also possible to specify a custom RabbitListenerEndpointRegistry
in case you need more control on the way the containers
are created and managed. The example below also demonstrates how to customize the
RabbitHandlerMethodFactory
to use with a custom Validator
so that payloads annotated with Validated
are first validated against a custom Validator
.
@Configuration @EnableRabbit public class AppConfig implements RabbitListenerConfigurer { @Override public void configureRabbitListeners(RabbitListenerEndpointRegistrar registrar) { registrar.setEndpointRegistry(myRabbitListenerEndpointRegistry()); registrar.setMessageHandlerMethodFactory(myMessageHandlerMethodFactory); } @Bean public RabbitListenerEndpointRegistry<?> myRabbitListenerEndpointRegistry() { // registry configuration } @Bean public RabbitHandlerMethodFactory myMessageHandlerMethodFactory() { DefaultRabbitHandlerMethodFactory factory = new DefaultRabbitHandlerMethodFactory(); factory.setValidator(new MyValidator()); return factory; } @Bean public MyService myService() { return new MyService(); } }For reference, the example above can be compared to the following Spring XML configuration:
<beans>
<rabbit:annotation-driven registry="myRabbitListenerEndpointRegistry"
handler-method-factory="myRabbitHandlerMethodFactory"/>
<bean id="myRabbitListenerEndpointRegistry"
class="org.springframework.amqp.rabbit.config.RabbitListenerEndpointRegistry">
// registry configuration
</bean>
<bean id="myRabbitHandlerMethodFactory"
class="org.springframework.amqp.rabbit.config.DefaultRabbitHandlerMethodFactory">
<property name="validator" ref="myValidator"/>
</bean>
<bean id="myService" class="com.acme.foo.MyService"/>
</beans>
Implementing RabbitListenerConfigurer
also allows for fine-grained
control over endpoints registration via the RabbitListenerEndpointRegistrar
.
For example, the following configures an extra endpoint:
@Configuration @EnableRabbit public class AppConfig implements RabbitListenerConfigurer { @Override public void configureRabbitListeners(RabbitListenerEndpointRegistrar registrar) { SimpleRabbitListenerEndpoint myEndpoint = new SimpleRabbitListenerEndpoint(); // ... configure the endpoint registrar.registerEndpoint(endpoint, anotherRabbitListenerContainerFactory()); } @Bean public MyService myService() { return new MyService(); } @Bean public RabbitListenerContainerFactory<?> anotherRabbitListenerContainerFactory() { // ... } // Rabbit infrastructure setup }Note that all beans implementing
RabbitListenerConfigurer
will be detected and
invoked in a similar fashion. The example above can be translated in a regular bean
definition registered in the context in case you use the XML configuration.RabbitListener
,
RabbitListenerAnnotationBeanPostProcessor
,
RabbitListenerEndpointRegistrar
,
RabbitListenerEndpointRegistry