ChannelInterceptor:
- Message被发送到线程池,在发送动作执行前(后)拦截,发生在当前线程。
ExecutorChannelInterceptor:
- Message被发送到线程池后,在线程池持有的新线程中,在MessageHandler处理前(后)拦截。
这里以,为InboundChannel配置ChannelInterceptor为例
- 在WebSocketMessageBrokerConfigurer中配置拦截器:
WebSocketMessageBrokerConfigurer:
@Override
public void configureClientInboundChannel(ChannelRegistration registration) {
registration.interceptors(new ChannelInterceptor() {
@Override
public Message<?> preSend(Message<?> message, MessageChannel channel) {
StompHeaderAccessor accessor = MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class);
StompCommand command = accessor.getCommand();
log.info(command.toString());
log.info(JSON.toJSONString(message));
if (StompCommand.CONNECT.equals(accessor.getCommand())) {
String id = accessor.getFirstNativeHeader("id");
accessor.setUser(new IdPrincipal(id));
}
return message;
}
});
}
- 从WebSocketMessageBrokerConfigurer配置中读取登记过的拦截器
AbstractMessageBrokerConfiguration:
@Bean
public AbstractSubscribableChannel clientInboundChannel() {
ExecutorSubscribableChannel channel = new ExecutorSubscribableChannel(clientInboundChannelExecutor());
ChannelRegistration reg = getClientInboundChannelRegistration();
if (reg.hasInterceptors()) {
channel.setInterceptors(reg.getInterceptors());
}
return channel;
}
- 将通道拦截器绑定到ExecutorSubscribableChannel上,同时为拦截器分类
ChannelInterceptor
和ExecutorChannelInterceptor
,添加到相应集合中
ExecutorSubscribableChannel:
@Override
public void setInterceptors(List<ChannelInterceptor> interceptors) {
super.setInterceptors(interceptors);
this.executorInterceptors.clear();
for (ChannelInterceptor interceptor : interceptors) {
if (interceptor instanceof ExecutorChannelInterceptor) {
this.executorInterceptors.add((ExecutorChannelInterceptor) interceptor);
}
}
}
- 普通的ChannelInterceptor,被内部类
AbstractMessageChannel$ChannelInterceptorChain
构造成拦截器链,这个拦截器链的所有实现方法都以外部类AbstractMessageChannel实例所持有的interceptors
集合为核心,进行拦截器的调用。 - 拦截器链的调用发生在AbstractMessageChannel实例的send方法中,在sendInternal方法执行前后同步调用,发生在当前线程。
AbstractMessageChannel:
public abstract class AbstractMessageChannel implements MessageChannel, InterceptableChannel, BeanNameAware {
private final List<ChannelInterceptor> interceptors = new ArrayList<ChannelInterceptor>(5);
@Override
public final boolean send(Message<?> message, long timeout) {
Assert.notNull(message, "Message must not be null");
ChannelInterceptorChain chain = new ChannelInterceptorChain();
boolean sent = false;
try {
message = chain.applyPreSend(message, this);
if (message == null) {
return false;
}
sent = sendInternal(message, timeout);
chain.applyPostSend(message, this, sent);
chain.triggerAfterSendCompletion(message, this, sent, null);
return sent;
}
catch (Exception ex) {
chain.triggerAfterSendCompletion(message, this, sent, ex);
if (ex instanceof MessagingException) {
throw (MessagingException) ex;
}
throw new MessageDeliveryException(message,"Failed to send message to " + this, ex);
}
catch (Throwable err) {
MessageDeliveryException ex2 =
new MessageDeliveryException(message, "Failed to send message to " + this, err);
chain.triggerAfterSendCompletion(message, this, sent, ex2);
throw ex2;
}
}
protected class ChannelInterceptorChain {
private int sendInterceptorIndex = -1;
private int receiveInterceptorIndex = -1;
public Message<?> applyPreSend(Message<?> message, MessageChannel channel) {
Message<?> messageToUse = message;
for (ChannelInterceptor interceptor : interceptors) {
Message<?> resolvedMessage = interceptor.preSend(messageToUse, channel);
if (resolvedMessage == null) {
String name = interceptor.getClass().getSimpleName();
if (logger.isDebugEnabled()) {
logger.debug(name + " returned null from preSend, i.e. precluding the send.");
}
triggerAfterSendCompletion(messageToUse, channel, false, null);
return null;
}
messageToUse = resolvedMessage;
this.sendInterceptorIndex++;
}
return messageToUse;
}
public void applyPostSend(Message<?> message, MessageChannel channel, boolean sent) {
for (ChannelInterceptor interceptor : interceptors) {
interceptor.postSend(message, channel, sent);
}
}
}
}
- InboundChannel实例通过sendInternal方法,将Message与MessageHandler封装成SendTask,发送到支撑自己的ThreadPoolTaskExecutor线程池,在新的线程中异步处理Message;
- 在新的线程中,在SendTask的run方法里,通过
MessageHandler.handleMessage(Message)
方法对Message进行处理,在handleMessage前后调用executorInterceptors
集合,进行拦截;
ExecutorSubscribableChannel :
public class ExecutorSubscribableChannel extends AbstractSubscribableChannel {
private final Executor executor;
private final List<ExecutorChannelInterceptor> executorInterceptors = new ArrayList<ExecutorChannelInterceptor>(4);
@Override
public boolean sendInternal(Message<?> message, long timeout) {
for (MessageHandler handler : getSubscribers()) {
SendTask sendTask = new SendTask(message, handler);
if (this.executor == null) {
sendTask.run();
}
else {
this.executor.execute(sendTask);
}
}
return true;
}
private class SendTask implements MessageHandlingRunnable {
@Override
public void run() {
Message<?> message = this.inputMessage;
try {
message = applyBeforeHandle(message);
if (message == null) {
return;
}
this.messageHandler.handleMessage(message);
triggerAfterMessageHandled(message, null);
}
catch (Exception ex) {
triggerAfterMessageHandled(message, ex);
if (ex instanceof MessagingException) {
throw (MessagingException) ex;
}
String description = "Failed to handle " + message + " to " + this + " in " + this.messageHandler;
throw new MessageDeliveryException(message, description, ex);
}
catch (Throwable err) {
String description = "Failed to handle " + message + " to " + this + " in " + this.messageHandler;
MessageDeliveryException ex2 = new MessageDeliveryException(message, description, err);
triggerAfterMessageHandled(message, ex2);
throw ex2;
}
}
private Message<?> applyBeforeHandle(Message<?> message) {
Message<?> messageToUse = message;
for (ExecutorChannelInterceptor interceptor : executorInterceptors) {
messageToUse = interceptor.beforeHandle(messageToUse, ExecutorSubscribableChannel.this, this.messageHandler);
if (messageToUse == null) {
String name = interceptor.getClass().getSimpleName();
if (logger.isDebugEnabled()) {
logger.debug(name + " returned null from beforeHandle, i.e. precluding the send.");
}
triggerAfterMessageHandled(message, null);
return null;
}
this.interceptorIndex++;
}
return messageToUse;
}
private void triggerAfterMessageHandled(Message<?> message, Exception ex) {
for (int i = this.interceptorIndex; i >= 0; i--) {
ExecutorChannelInterceptor interceptor = executorInterceptors.get(i);
try {
interceptor.afterMessageHandled(message, ExecutorSubscribableChannel.this, this.messageHandler, ex);
}
catch (Throwable ex2) {
logger.error("Exception from afterMessageHandled in " + interceptor, ex2);
}
}
}
}
}