【问题标题】:org.springframework.web.client.RestTemplate expected to be declared as @Bean and plain @Autowired throws errororg.springframework.web.client.RestTemplate 期望被声明为@Bean 和普通的@Autowired 抛出错误
【发布时间】:2019-09-27 10:46:28
【问题描述】:

我在@RestController 类“personController”中需要一个 RestTemplate 对象,所以我如下声明它。

@Autowired
 private RestTemplate restTemplate;

当我尝试使用它时,我收到以下错误 com.example.demo.api.PersonController 中的字段 restTemplate 需要一个无法找到的 org.springframework.web.client.RestTemplate 类型的 bean。 考虑在您的配置中定义一个 org.springframework.web.client.RestTemplate 类型的 bean。

为了克服这个错误,我在 config.java 文件中为 restemplate 声明了一个@Bean,如下所示,它工作正常并且没有抛出任何错误。

@Bean
public RestTemplate restTemplate() {
    RestTemplate restTemplate = new RestTemplate();
    return restTemplate;
}

我在@Service 类“personService”中使用com.fasterxml.jackson.databind.ObjectMapper 对象,我像下面这样自动连接它。

@Autowired
private ObjectMapper objectMapper;

我能够使用 objectmapper 而不为它声明任何 bean 并且它工作正常。 我想了解

  1. 为什么 objectmapper 可以在没有 bean 的情况下工作,而 resttemplate 不能 在没有 bean 的情况下工作并期望声明一个 bean?
  2. 何时创建 bean 以及何时简单地使用纯 @Autowired 而无需 豆?怎么看才知道?

【问题讨论】:

    标签: java spring rest spring-boot spring-mvc


    【解决方案1】:

    正如春季文档中提到的那样。 https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-resttemplate.html

    如果您需要从应用程序调用远程 REST 服务,您可以使用 Spring Framework 的 RestTemplate 类。由于 RestTemplate 实例通常需要在使用前进行自定义,因此 Spring Boot 不提供任何单个自动配置的 RestTemplate bean。但是,它会自动配置一个 RestTemplateBuilder,它可用于在需要时创建 RestTemplate 实例。自动配置的 RestTemplateBuilder 可确保将合理的 HttpMessageConverters 应用于 RestTemplate 实例。

    【讨论】:

      【解决方案2】:

      ObjectMapper 之所以有效,是因为有其他第 3 方(即 Jackson)代码使用该 bean(并且由他们配置)。您只是通过将其自动装配到您自己的 bean 来利用这一点。

      另一方面,

      RestTemplate 不是由 your 代码库中的第 3 方作为 bean 提供的(它可能来自依赖项)。因此,如果您愿意,您可以自己创建一个 bean。

      除非您知道任何东西,否则您不能假设任何东西都是 bean,因此文档是您首先要查看的地方。

      【讨论】:

      • 谢谢。我在 spring-boot-autoconfigure-2.1.8.jar 的 spring-autoconfigure-metadata.properties 文件中找到了“org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration.ConditionalOnClass=com.fasterxml.jackson.databind.ObjectMapper”。这是在做自动配置吗?在哪里可以看到 springboot 自动配置的所有类的列表?
      【解决方案3】:

      ObjectMapper bean 是由 Spring Boot 创建的,因为您的类路径中存在 ObjectMapper 类并触发 JacksonAutoConfiguration。这就是为什么您可以在不显式创建它的情况下自动装配这个 bean。

      另一方面,RestTemplate 是你必须自己创建的 bean - Spring 不会为你做这件事,因为没有自动配置类可以触发它的创建。

      【讨论】:

      • 谢谢。我在 spring-boot-autoconfigure-2.1.8.jar 的 spring-autoconfigure-metadata.properties 文件中找到了“org.springframework.boot.autoconfigure.jackson.JacksonAutoConfiguration.ConditionalOnClass=com.fasterxml.jackson.databind.ObjectMapper”。这是在做自动配置吗?在哪里可以看到 springboot 自动配置的所有类的列表?
      • 是的,当您的类路径中有ObjectMapper 时,该类中定义的所有bean 都由Spring 创建。您可以在此处找到所有自动配置类:github.com/spring-projects/spring-boot/tree/master/…。您可以使用 @EnableAutoConfiguration(exclude = {[classes to be excluded]} 注释排除任何自动配置类。
      【解决方案4】:

      ObjectMapper 很可能是通过您项目的交叉重新引用或传递依赖项之一进入上下文,但 RestTemplate 不是。所以ObjectMapper 的实例是隐式创建的,而RestTemplate 根本没有创建。所以这就是你必须显式创建 RestTemplate 的 bean 的原因。

      【讨论】:

        【解决方案5】:

        正如其他用户所说,这是正确的,spring 没有为 RestTemplate 定义默认 bean。首选方法是使用 org.springframework.boot.web.client.RestTemplateBuilder 构建其余模板。

        下面给出一个例子。

        @Service
        public class RestServiceCaller {
        
          private RestTemplate restTemplate;
        
          @Autowired
          RestServiceCaller(RestTemplateBuilder builder) {
             restTemplate = builder.build();
          }
        
         ........
         .....//here you will have other methods which make use of this restTemplate
        }
        

        来自restTemplateBuilder的JavaDoc -> “在典型的自动配置 Spring Boot 应用程序中,此构建器可作为 bean 使用,并且可以在需要 RestTemplate 时注入。”

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2021-12-29
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多