ChatGPT解决这个技术问题 Extra ChatGPT

Spring 在没有 @Autowired 注释的构造函数中注入依赖项

我正在试验来自这个官方 Spring tutorials 的示例,并且依赖于此代码:
https://github.com/spring-guides/gs-async-method/tree/master/complete

如果您查看 AppRunner.java 类的代码,我有 2 个问题:

当服务器启动时,如果我在此类的构造函数中放置一个断点,就像在构造函数中一样,GitHubLookupService 是由 spring 提供的,使用配置的 @Service bean。但是,构造函数上没有 @Autowired 注释,那么这个构造函数到底是如何以正确的依赖关系调用的呢?它应该是空的。

它是 Spring Boot 的自动假设吗? Spring 是否看到“私有字段 + 构造函数参数,并假定它应该寻找合适的 bean?是 Spring Framework 还是 Spring boot?我错过了什么吗?

我记得,为 bean / 服务等提供默认构造函数是强制性的。为什么这个类(AppRunner)没有默认构造函数? Spring 如何知道它应该使用参数运行构造函数?是因为它是唯一的构造函数吗?


M
M. Deinum

从 Spring4.3 开始,如果配置为 Spring bean 的类只有一个构造函数,则可以省略 @Autowired 注释,Spring 将使用该构造函数并注入所有必要的依赖项。

关于默认构造函数:您需要默认构造函数,当您有多个构造函数时需要一个带有 @Autowired 注释的构造函数,或者您的类中只有一个带有或不带有 @Autowired 注释的构造函数。

阅读 Spring 官方文档中的 @Autowired 章节以了解更多信息。


我有一个类似的问题,只是我的类没有被注释为 Bean!事实上,它根本没有注释! Spring 仍然尝试自动装配构造函数并失败,因为没有找到与构造函数参数的类型匹配的 Bean。然而,该类确实扩展了 PropertySource。这可能是原因吗?有没有办法避免这种自动装配?
这里引用官方文档:从 Spring Framework 4.3 开始,如果目标 bean 仅定义一个构造函数开始,则不再需要在此类构造函数上添加 @Autowired 注释。但是,如果有多个构造函数可用,则必须至少对其中一个进行注释以告知容器使用哪一个。
M
Michael

这样想……假设您有以下组件:

@Component 
public class FooService {
    public FooService(Bar bar) { /*whatever*/ }
}

当 Spring 扫描这个类时,它想知道它应该如何构造一个实例。它使用反射,因此它可以在运行时获取所有构造函数的列表。

在这种情况下,Spring 必须如何构造这个实例是完全明确的。只有一个构造函数,因此无需做出任何决定,也没有任何歧义。

如果在此处添加 @Autowired,则不会缩小任何范围,也不会向 Spring 提供任何额外信息来帮助其做出决定——它的决定已经做出,因为只有一个候选人。

因此,为方便起见,Spring 团队决定 @Autowired 应该是可选的。由于它不帮助 Spring 框架做出决定,它的存在只是噪音。

如果您的组件有多个构造函数,那么您可以在其中一个上使用 @Autowired 来告诉 Spring“使用这个,而不是那个”。


很好的解释,完全有道理。谢谢。我只是创建了一个使用@Service 注释的服务类,并尝试执行 autowire Service srv;在我的 Controller 类中,并期望 Spring 能够让我获得该服务的 bean,假设它将使用 Default 构造函数实现。但相反,我需要提供无参数或参数化构造函数。