RestTemplate 线程安全吗?

2022-08-31 13:12:04

弹簧线安全吗?那是RestTemplate

  • 是多个连接可以安全共享的策略对象。RestTemplate
  • 是一个连接对象(类似于数据库连接),在使用时无法共享,并且需要为每个连接重新创建或池化。RestTemplate

答案 1

RestTemplate 是线程安全的(着重号是后加的):

从概念上讲,它与 Spring 框架和其他项目组合项目中的 、 和 各种其他模板非常相似。这意味着,例如,RestTemplate 在构造后是线程安全的。JdbcTemplateJmsTemplate


该类的对象不会更改其任何状态信息来处理HTTP:该类是Strategy设计模式的实例,而不是像连接对象一样。在没有状态信息的情况下,如果不同的线程共享一个对象,则不可能损坏或竞速状态信息。这就是线程可以共享这些对象的原因。RestTemplateRestTemplate

如果检查 RestTemplate 的源代码,您会发现它在构造对象后不使用方法或字段来提供线程安全。因此,在构造后修改对象是不安全的。特别是,添加消息转换器是不安全的。synchronizedvolatileRestTemplate

若要为其提供消息转换器列表,必须执行下列操作之一:

  • 使用构造函数。由于 的内部列表是 ,这可以安全地发布消息转换器的列表RestTemplate(List<HttpMessageConverter<?>> messageConverters)messageConvertersfinal
  • 使用赋值器,然后安全地发布已更改的对象。使用具有此功能的Spring Bean定义,因为在大多数实际用例中,设置容器的线程将安全地发布Bean。setMessageConverters(List<HttpMessageConverter<?>> messageConverters)RestTemplate<property name="messageConverters"><list>...
  • 在 返回的引用上使用,然后安全地发布已更改的对象。但是,的文档没有明确说明它返回可用于更改消息转换器列表的引用。当前实现可以,但可能会更改实现以返回列表的或副本。因此,最好不要以这种方式更改它。List.addgetMessageConverters()RestTemplateRestTemplateCollections.unmodifiableList

请注意,第一种情况是在构造对象时设置消息转换器的唯一方法,因此说它“一旦构造就线程安全”是正确的

该类是Spring框架的一部分,因此在几乎所有实际情况下,该类的对象都将设置为Spring应用程序上下文的一部分,使用第一种方法(使用构造函数进行依赖关系注入)或第二种方法(使用 setter 进行依赖关系注入),因此可以保证安全地发布到多个线程。


答案 2

从库的角度来看,它是线程安全的。例如,getMessageConverters() 是公共的,这意味着如果有人在列表上持有并在库的目的之外对其进行修改,那么它将导致问题(甚至是 setter 方法,如果在 RestTemplate 实例化后的任何时刻调用它 - 并且显然被其他线程使用,boom!)。这可能就是Ross发生的事情(没有足够的声誉来回复答案,但我正在备份线程安全和非线程安全参数)