文章目录
- ChannelInterceptor:
- ExecutorChannelInterceptor:
- 这里以,为InboundChannel配置ChannelInterceptor为例
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);
}
}
}
}
}