Spring RestTemplate
线程安全吗?那是
RestTemplate
策略对象,多个连接可以安全地共享。 或 RestTemplate
连接对象(如数据库连接),在使用时无法共享,需要为每个连接重新创建或汇集。答案 0 :(得分:76)
RestTemplate
is thread safe(强调补充):
从概念上讲,它与
JdbcTemplate
,JmsTemplate
以及Spring Framework和其他项目组合项目中的各种其他模板非常相似。这意味着,例如,RestTemplate
一旦构建就是线程安全的
RestTemplate
类的对象不会更改任何状态信息来处理HTTP:该类是策略设计模式的一个实例,而不是像连接对象。如果没有状态信息,则如果共享RestTemplate
对象,则不会有不同的线程破坏或竞争状态信息。这就是线程可以共享这些对象的原因。
如果您检查the source code of RestTemplate
,您会发现在构造对象后,它不会使用synchronized
方法或volatile
字段来提供线程安全性。因此,构建后修改RestTemplate
对象不是安全的。特别是,添加消息转换器是不安全的。
要为其提供消息转换器列表,您必须执行以下操作之一:
RestTemplate(List<HttpMessageConverter<?>> messageConverters)
构造函数。由于messageConverters
的内部列表为final
,因此safely publishes the list of message converters。setMessageConverters(List<HttpMessageConverter<?>> messageConverters)
mutator 和,然后使用safely-publish更改的RestTemplate
对象。在大多数实际使用案例中,使用具有<property name="messageConverters"><list>...
的Spring bean定义作为bean will be safely published by the thread setting up the container。List.add
返回的引用使用getMessageConverters()
,然后安全地发布已更改的RestTemplate
对象。但是,RestTemplate
的文档未明确声明它返回可用于更改消息转换器列表的引用。当前的实现确实如此,但可能会更改实现以返回Collections.unmodifiableList
或列表的副本。所以最好不要这样改变它。请注意,第一种情况是在构造对象时设置消息转换器的唯一方法,因此 正确地说它一旦构造就是线程安全的&#34;
该类是Spring Framework的一部分,因此在几乎所有实际情况中,类的对象将被设置为Spring Application Context的一部分,使用第一个(使用构造函数的依赖注入)或第二个(使用依赖注入)一个setter)方法,因此可以保证安全地发布到多个线程。
答案 1 :(得分:1)
从库的角度来看,它是线程安全的。例如,getMessageConverters()是公共的,这意味着如果有人抓住列表并在库的目的之外修改它,那么它将导致问题(甚至是setter方法,如果在RestTemplate实例化之后的任何时候调用它 - 显然,当被其他线程使用时,繁荣!)。这可能是Ross发生的事情(没有足够的声誉回复答案,但我正在备份线程安全和非线程安全的参数)
答案 2 :(得分:0)
好吧,虽然我可能会从导致这些问题的源代码控制中挖出旧代码。
我认为,即使在创建时进行同步,也存在另一个线程可以修改内部集合的情况。所以最好小心点。 看看旧代码,是的,它实际上是使用消息转换器。但只有在创作时同步。
restTemplate = new RestTemplate();
restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
之后,与RestTemplate的唯一互动是:
return restTemplate.postForObject(url, object, clazz);
这也是最终抛出异常的行。
当然没有与消息转换器的交互(我们没有本地引用它)。
查看堆栈跟踪和spring源代码,错误发生在以下行:
for (HttpMessageConverter<?> converter : getMessageConverters()) {
那我们有什么?
总而言之,在某些情况下,事情可能不是线程安全的,当然如果您直接使用消息转换器。这种情况虽然很奇怪,但我认为发布它会很有用。
答案 3 :(得分:-1)
讨厌不同意上面接受的答案(强调添加),但不是不是线程安全。即使在创作之后。在内部,它正在玩ArrayLists,我没有挖掘源。我见过太多这些:
java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:859)
at java.util.ArrayList$Itr.next(ArrayList.java:831)
at org.springframework.web.client.RestTemplate$AcceptHeaderRequestCallback.doWithRequest(RestTemplate.java:677)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:567)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:545)
at org.springframework.web.client.RestTemplate.getForObject(RestTemplate.java:253)