In addition to the XML namespace support for configuring Message Endpoints, it is also possible to use
      annotations. The class-level @MessageEndpoint annotation indicates that the
      annotated class is capable of being registered as an endpoint, and the method-level
      @Handler annotation indicates that the annotated method is capable of handling
      a message.
      
@MessageEndpoint(input="fooChannel") public class FooService { @Handler public void processMessage(Message message) { ... } }
The @MessageEndpoint is not required. If you want to configure a POJO reference from the "ref" attribute of a <service-activator/> element, it is sufficient to provide the @Handler method annotation. As long as the "annotation-driven" support is enabled, a Spring-managed object with that method annotation (or the others which are described below) will be post-processed such that it can be used as a reference from an XML-configured endpoint.
      In most cases, the annotated handler method should not require the Message type as its
      parameter. Instead, the method parameter type can match the message's payload type.
      
public class FooService { @Handler public void bar(Foo foo) { ... } }
      When the method parameter should be mapped from a value in the MessageHeader, another
      option is to use the parameter-level @Header annotation.
      
@MessageEndpoint(input="fooChannel") public class FooService { @Handler public void bar(@Header("foo") Foo foo) { ... } }
      As described in the previous section, when the handler method returns a non-null value, the endpoint will
      attempt to send a reply. This is consistent across both configuration options (namespace and annotations) in that
      the the endpoint's output channel will be used if available, and the message header's RETURN_ADDRESS value will be 
      the fallback. To configure the output channel for an annotation-driven endpoint, provide the 'output'
      attribute on the @MessageEndpoint.
      
@MessageEndpoint(input="exampleChannel", output="replyChannel")
      Just as the 'poller' sub-element and its 'period' attribute can be provided for a namespace-based
      endpoint, the @Poller annotation can be provided with the
      @MessageEndpoint annotation.
      
@MessageEndpoint(input="exampleChannel") @Poller(period=3000) public class FooService { ... }
      Likewise, @Concurrency provides an annotation-based equivalent of the
      <pool-executor/> element:
      
@MessageEndpoint(input="fooChannel") @Concurrency(coreSize=5, maxSize=20) public class FooService { @Handler public void bar(Foo foo) { ... } }
      Several additional annotations are supported, and three of these act as a special form of handler method:
      @Router, @Splitter and
      @Aggregator. As with the @Handler annotation,
      methods annotated with these annotations can either accept the Message itself, the
      message payload, or a header value (with @Header) as the parameter. In fact, the method can accept a combination,
      such as:
      
someMethod(String payload, @Header("x") int valueX, @Header("y") int valueY);
      When using the @Router annotation, the annotated method can return either the
      MessageChannel or String type. In the case of the latter,
      the endpoint will resolve the channel name as it does for the default output. Additionally, the method can return
      either a single value or a collection. When a collection is returned, the reply message will be sent to multiple
      channels. To summarize, the following method signatures are all valid.
      
@Router public MessageChannel route(Message message) {...} @Router public List<MessageChannel> route(Message message) {...} @Router public String route(Foo payload) {...} @Router public List<String> route(Foo payload) {...}
      In addition to payload-based routing, a common requirement is to route based on metadata available within the
      message header as either a property or attribute. Rather than requiring use of the
      Message type as the method parameter, the @Router
      annotation may also use the same @Header parameter annotation that was introduced above.
      
@Router public List<String> route(@Header("orderStatus") OrderStatus status)
      The @Splitter annotation is also applicable to methods that expect either the
      Message type or the message payload type, and the return values of the method
      should be a collection of any type. If the returned values are not actual Message
      objects, then each of them will be sent as the payload of a message. Those messages will be sent to the output
      channel as designated for the endpoint on which the @Splitter is defined.
      
@Splitter
List<LineItem> extractItems(Order order) {
    return order.getItems()
}
      The @Aggregator annotation may be used on a method that accepts a collection
      of Messages or Message payload types and whose return value is a single Message or single Object that will
      be used as the payload of a Message.
      
@Aggregator public Message<?> aggregateMessages(List<Message<?>> messages) { ... } @Aggregator public Order aggregateOrder(List<LineItem> items) { ... }
      Finally, the @Publisher is an annotation that triggers the creation of a Spring
      AOP Proxy such that the return value, exception, or method invcation arguments can be sent to a Message Channel.
      For example, each time the following method is invoked, its return value will be sent to the "fooChannel":
      
@Publisher(channel="fooChannel") public String foo() { return "bar"; }
The return value is published by default, but you can also configure the payload type:
@Publisher(channel="testChannel", payloadType=MessagePublishingInterceptor.PayloadType.ARGUMENTS)
public void publishArguments(String s, Integer n) {
    ...
}
@Publisher(channel="testChannel", payloadType=MessagePublishingInterceptor.PayloadType.EXCEPTION)
public void publishException() {
    throw new RuntimeException("oops!");
}