Java spring rabitmq和线程本地-何时是调用clean方法的好时机

Java spring rabitmq和线程本地-何时是调用clean方法的好时机,java,spring-integration,spring-amqp,spring-rabbit,Java,Spring Integration,Spring Amqp,Spring Rabbit,我有一个@RabbitListener,正在队列中正常工作。 在我的听者中,我设置了上下文 我知道有许多(可配置的)线程使用相同的队列(因此在实际执行相同的lisener代码时) 现在,我想,什么时候是理清背景的好时机 更准确地说,我要表达的问题是: “当您结束消费时(无论是否异常),请清除上下文)” 下面,您可以看到我的问题的解决方案: public class CustomContextHolder { private static final ThreadLocal<Data

我有一个
@RabbitListener
,正在队列中正常工作。 在我的听者中,我设置了上下文

我知道有许多(可配置的)线程使用相同的队列(因此在实际执行相同的lisener代码时)

现在,我想,什么时候是理清背景的好时机

更准确地说,我要表达的问题是:

“当您结束消费时(无论是否异常),请清除上下文)”

下面,您可以看到我的问题的解决方案:

public class CustomContextHolder {

   private static final ThreadLocal<DatabaseType> contextHolder = 
            new ThreadLocal<DatabaseType>();

   public static void setContext(DatabaseType databaseType) {
      contextHolder.set(databaseType);
   }

   public static CustomerType getContext() {
      return (CustomerType) contextHolder.get();
   }

   public static void clearContext() {
      contextHolder.remove();
   }
}


@RabbitListener
void listenMessage(Message message) {
  ...
  CustomContextHolder.set(...);

}
公共类CustomContextHolder{
私有静态最终线程本地上下文持有者=
新ThreadLocal();
公共静态void setContext(DatabaseType DatabaseType){
contextHolder.set(数据库类型);
}
公共静态CustomerType getContext(){
return(CustomerType)contextHolder.get();
}
公共静态void clearContext(){
contextHolder.remove();
}
}
@兔八哥
无效列表消息(消息消息消息){
...
CustomContextHolder.set(…);
}

通常最好使用无状态对象作为侦听器,而不是使用
ThreadLocal

但是,如果您被迫以这种方式保持状态,则可以实现
ApplicationListener

ApplicationListener
将接收多个事件;具体来说,当使用者正常停止时,
AsyncConsumerStoppedEvent
,如果使用者异常停止时,
ListenerContainerConsumerFailedEvent
。这两个事件发布在侦听器线程上,因此您可以在那里清除
ThreadLocal


其他事件可能在侦听器线程上发布,也可能不在侦听器线程上发布。

我认为,由于您的使用者实际上可能是异步的,因此您的问题没有“无处不在”的答案。一般来说,我认为如果你需要这样的行为,你就可以用这样的方式来构造你的应用程序:所有的用户都被截取,“在前”设置上下文,然后在“后”中清除它。根据这个线程,你能考虑我的问题吗?这就是为什么我必须使用thRead本地的原因,但是我知道在这种情况下它并不优雅。(如果每条消息的上下文都发生了变化)您需要在侦听器方法的末尾清除(可能在finally块中)。我假设您希望在线程的生命周期内保留它。我必须保留上下文,因为每条消息都需要对数据库进行一些操作。数据库的选择取决于消息。数据源路由器根据上下文进行选择,因此必须为每条消息设置上下文。第二件事是,对于请求(取决于用户),我也设置了上下文(所以数据库使数据源路由器选择数据源成为可能)。所以您建议最后在侦听器方法中,或者实现两个侦听器:
AsyncConsumerStoppedEvent
ListenerContainerConsumerFailedEvent
。我可以阅读一些关于侦听器的信息吗(我想知道线程何时执行…)如果每个消息的上下文都需要更改,那么事件解决方案将不适用于您。请忽略这一点。好的,我可以向您解释为什么需要此上下文。因此
最后尝试{clearContext}
@RabbitListener
中的
对我来说是唯一可能的。是
spring-rabbitmq
为每条消息创建线程?还是为循环中的消息服务的线程池?