【问题标题】:Spring automatically injects method parametersSpring自动注入方法参数
【发布时间】:2020-07-29 22:18:25
【问题描述】:

我已经开始学习spring了,对此我有点困惑: 如果我创建一个 spring @Controller 或 @RestController 然后在方法中我要求不同的参数,我注意到即使没有将它们声明为 bean 或组件,spring 也会自动填充这些参数。

所以在我的项目中,我有一个 Movie 类(一个简单的 POJO),我也需要一个 RestTemplate 的单例实例。第一种方法是声明 RestTemplate bean,然后使用 @Autowired 请求它,这工作正常。之后,我注释掉了那部分代码并将 RestTemplate 和 Movie 作为我的方法的参数,即使我没有任何 bean 声明,spring 也会自动为我提供这些实例。

我认为 spring 利用 bean 声明来进行依赖注入,所以我的问题是,如果 spring 已经在方法中注入了我想要的任何东西,为什么我必须声明 bean 并使用 @Autowired? spring 是否注入这些参数的单例实例?这可以使用还是更好地贴花豆并通过@Autowired?

类下:

这是我的电影模型:

import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
public class Movie {

    private String movieId;
    private String name;
    
}

这是我的休息控制器:

@RestController
@RequestMapping("/catalog")
public class MovieCatalogController {
    
    //@Autowired
    //private RestTemplate restTemplate;

    @RequestMapping("/{userId}")
    public List<Catalog> getCatalog(@PathVariable("userId") String userId, RestTemplate restTemplate, Movie movie){
        // todo
        return new ArrayList<>();
    }

}

以及主要的spring boot应用类:

@SpringBootApplication
public class MovieCatalogServiceApplication {
    
    //@Bean
    //public RestTemplate getRestTemplate() {
        //return new RestTemplate();
    //}

    public static void main(String[] args) {
        SpringApplication.run(MovieCatalogServiceApplication.class, args);
    }

}

谢谢

【问题讨论】:

  • 它不会注入到方法中,它实际上会创建一个新的RestTEmplate,而不是使用上下文中的那个。这也是 Spring MVC 特有的,因为它将构造它现在没有的对象并将它们用作模型属性并将请求中的参数绑定到它。您应该做的是在您的类中自动装配它(并且当您使用 Spring Boot 时,您不需要将 RestTemplate 定义为 Spring Boot 自动提供的 bean)。
  • 感谢您的回复 Deinum。所以这不是 DI 案例,而是 spring mvc 模型对象的行为,对吗?对于 RestTemplate bean,如果我删除 bean 定义,它会给我一个错误:“需要一个无法找到的 'org.springframework.web.client.RestTemplate' 类型的 bean。”
  • 这确实不是 DI 案例,而是 Spring MVC 行为。关于错误,这很奇怪,如果您使用 Spring Boot(正确!)它会提供一个。

标签: java spring spring-boot spring-mvc


【解决方案1】:

您所指的称为方法注入。只要有一个实现,任何组件都可以注入(您可以指定在配置文件或@Qualifier annotation 不是这种情况时要使用的实现)

类的实例数由@scope 决定。 Singleton is the default scope 所以你应该没问题,不需要使用你的 bean 定义。

@autowired 现在有点老了,但仍然有它的用途。虽然对于基本注入it is preferred to use constructor or method injection.

我自己对 Spring 还很陌生,所以我可能错了

【讨论】:

  • 不,不是,Spring 实际上会为此方法创建一个 RestTemplate 的新实例,而不是使用上下文中的实例。
  • 感谢德米安的回复。我认为我们只使用 setter 进行方法注入,但在这种情况下,我的 getCatalog 方法是我的控制器的一部分,它要求更多参数
  • @M.Deinum 你能澄清一下吗?你的意思是因为它的方法注入还是一般? @Eddie 为什么不直接注入构造函数 MovieCatalogController(RestTemplate template) { this.template=template}
  • 这里发生的是 Spring MVC 的一个特性,它创建一个类的实例并将其用作模型对象。因此,由于 Spring MVC,它不是 DI,而是模型对象构造。当您将 1 个或多个依赖项传递给该方法时,在 @Bean 注释的方法中使用方法注入。
猜你喜欢
  • 2018-01-29
  • 2013-07-13
  • 1970-01-01
  • 2018-07-27
  • 2015-05-22
  • 1970-01-01
  • 2017-08-03
  • 2021-04-12
  • 1970-01-01
相关资源
最近更新 更多