Context Holder Advice

从 6.1 版本开始,引入了 ContextHolderRequestHandlerAdvice。此建议从请求消息中获取一些值,并将其存储在上下文持有者中。当目标 MessageHandler 上的执行完成时,值会从上下文中清除。考虑此建议的最好方法类似于编程流程,我们在其中将一些值存储到 ThreadLocal 中,从目标调用中获取它,然后在执行后清理 ThreadLocalContextHolderRequestHandlerAdvice 需要这些构造函数参数:一个 Function<Message<?>, Object> 作为值提供者、Consumer<Object> 作为上下文设置回调和 Runnable 作为上下文清理钩子。

Starting with version 6.1, the ContextHolderRequestHandlerAdvice has been introduced. This advice takes some value from the request message as and stores it in the context holder. The value is clear from the context when an execution is finished on the target MessageHandler. The best way to think about this advice is similar to the programming flow where we store some value into a ThreadLocal, get access to it from the target call and then clean up the ThreadLocal after execution. The ContextHolderRequestHandlerAdvice requires these constructor arguments: a Function<Message<?>, Object> as a value provider, Consumer<Object> as a context set callback and Runnable as a context clean up hook.

以下是 ContextHolderRequestHandlerAdviceo.s.i.file.remote.session.DelegatingSessionFactory 配合使用的一个示例:

Following is a sample how a ContextHolderRequestHandlerAdvice can be used in combination with a o.s.i.file.remote.session.DelegatingSessionFactory:

@Bean
DelegatingSessionFactory<?> dsf(SessionFactory<?> one, SessionFactory<?> two) {
    return new DelegatingSessionFactory<>(Map.of("one", one, "two", two), null);
}

@Bean
ContextHolderRequestHandlerAdvice contextHolderRequestHandlerAdvice(DelegatingSessionFactory<String> dsf) {
    return new ContextHolderRequestHandlerAdvice(message -> message.getHeaders().get("FACTORY_KEY"),
                                      dsf::setThreadKey, dsf::clearThreadKey);
}

@ServiceActivator(inputChannel = "in", adviceChain = "contextHolderRequestHandlerAdvice")
FtpOutboundGateway ftpOutboundGateway(DelegatingSessionFactory<?> sessionFactory) {
	return new FtpOutboundGateway(sessionFactory, "ls", "payload");
}

将消息发送到 in 通道就足够了,该消息带有设置为 onetwoFACTORY_KEY 标头。ContextHolderRequestHandlerAdvice 通过其 setThreadKey 将该标头中的值设置到 DelegatingSessionFactory 中。然后,当 FtpOutboundGateway 执行 ls 命令时,会从 DelegatingSessionFactory 中根据其 ThreadLocal 中的值选择适当的委托 SessionFactory 。当从 FtpOutboundGateway 产生结果时,会根据 ContextHolderRequestHandlerAdvice 中的 clearThreadKey() 调用清除 DelegatingSessionFactory 中的 ThreadLocal 值。有关更多信息,请参阅 Delegating Session Factory

And it is just enough to send a message to the in channel with a FACTORY_KEY header set to either one or two. The ContextHolderRequestHandlerAdvice sets the value from that header into a DelegatingSessionFactory via its setThreadKey. Then when FtpOutboundGateway executes an ls command a proper delegating SessionFactory is chosen from the DelegatingSessionFactory according to the value in its ThreadLocal. When the result is produced from the FtpOutboundGateway, a ThreadLocal value in the DelegatingSessionFactory is cleared according to the clearThreadKey() call from the ContextHolderRequestHandlerAdvice. See Delegating Session Factory for more information.