Joshua
I can see how it might be a bit confusing when you start looking into the internals of the API, but you should really look at the Enterprise Integration Patterns (pretty much our requirement spec) definition of the Endpoint to get a better understanding.
http://www.eaipatterns.com/MessageEndpoint.html
In a nutshell Messaging Endpoint is the only component that is aware of the details of the messaging system, how it connects to channels etc.
It is the component that sits on two sides of the channel. It's job is to receive Messages from channels and pass them to Message Handlers (components that you implement) and then send them to output channels (if defined). The fact that we have AbstractMessageRouter, AbstractMessageSplitter etc., (which are implementations of MessageHandler interface), is to support POJO implementation of Routers, Splitters etc., as well as to support custom handler scenarios (routing vs splitting etc.) if you choose to extend those classes to build your own handlers.
Now, to answer your question as to why do we list Transformer, Filter, Router, Splitter, Aggregator, Service Activator as endpoints is because they are
(if you understand a few more implementation details)
If you look deeper into the implementation you'll see that we have two core endpoints EventDrivenConsumer and PollingConsumer. When you define let's say a Router the actual implementation of the AbstractMessageRouter (Message Handler) will be created and then the appropriate endpoint instance will also be created and then the MessageHandler will be injected into such endpoint so endpoint can invoke it once it receives the message.
Which type of endpoint will be created depends on your configuration.
For example:
Code:
<channel id="directChannel"/>
<router id="myRouter" input-channel="directChannel" .../>
In the above scenario your router endpoint is an EventDrivenConsumer which has an instance variable 'handler' which is your AbstractMessageRouter.
If you do applicationContext.getBean("myRouter") you will clearly see that what you'll get back is EventDrivenConsumer.
Here is slightly different config:
Code:
<channel id="queueChannel">
<queue capacity="10"/>
</channel>
<router id="myRouter" input-channel="queueChannel" ...>
<poller . . ./>
</router>
Although this configuration looks almost the same as the previous one the 'myRouter' will actually be encapsulated by a PollingConsumer since the endpoint for this router needs to poll the QueueChannel for messages and pass it to AbstractMessageRouter instance (handler).
The bottom line is Endpoint knows about messaging channels and how to interact with them - event-based or polling-based, essentially becoming a protocol-aware (polling or event) component. Message handlers are only aware of the message and not which channel it came from or how it was retrieved from such channel, thus keeping them reusable even if protocol changes.
I hope that explains.