Spring 在没有 @Autowired 注释的构造函数中注入依赖项
Posted
技术标签:
【中文标题】Spring 在没有 @Autowired 注释的构造函数中注入依赖项【英文标题】:Spring injects dependencies in constructor without @Autowired annotation 【发布时间】:2017-04-26 20:10:38 【问题描述】:我正在尝试来自这个官方 Spring tutorials 的示例,并且依赖于此代码:https://github.com/spring-guides/gs-async-method/tree/master/complete
如果您查看AppRunner.java
类的代码,我有两个问题:
-
当服务器启动时,如果我在这个类的构造函数中放置一个断点,似乎在构造函数中,
GitHubLookupService
是由 spring 提供的,使用配置的 @Service
bean。但是,构造函数上没有 @Autowired
注释,那么这个构造函数到底是如何使用正确的依赖关系调用的呢?应该是null
。
这是 Spring Boot 的自动假设吗? Spring 是否看到“私有字段 + 构造函数参数,并假设它应该寻找合适的 bean? 是 Spring Framework 还是 Spring boot? 我错过了什么吗?
-
我记得,为 bean / 服务等提供 默认构造函数 是强制性的。为什么这个类 (
AppRunner
) 没有默认构造函数?
Spring 如何知道它应该使用参数运行构造函数?
是因为它是唯一的构造函数吗?
【问题讨论】:
【参考方案1】:从 Spring4.3 开始,如果配置为 Spring bean 的类只有一个构造函数,则可以省略 @Autowired
注释,Spring 将使用该构造函数并注入所有必要的依赖关系。
关于默认构造函数:你要么需要默认构造函数,当你有多个构造函数时需要一个带有@Autowired
注解的构造函数,或者你的类中只有一个构造函数有或没有@Autowired
注释。
阅读官方 Spring 文档中的@Autowired
章节以获取更多信息。
【讨论】:
更相关的文档链接是docs.spring.io/spring/docs/4.3.x/spring-framework-reference/… 我也有类似的问题,只是我的类没有被注释为 Bean!事实上,它根本没有注释! Spring 仍然尝试自动装配构造函数并失败,因为没有找到与构造函数参数的类型匹配的 Bean。然而,该类确实扩展了PropertySource
。这可能是原因吗?有没有办法避免这种自动装配?【参考方案2】:
这样想...假设您有以下组件:
@Component
public class FooService
public FooService(Bar bar) /*whatever*/
当 Spring 扫描这个类时,它想知道它应该如何构造一个实例。它使用反射,因此它可以在运行时获取所有构造函数的列表。
在这种情况下,Spring 必须如何构造这个实例是完全明确的。只有一个构造函数,因此无需做出任何决定,也没有任何歧义。
如果您在此处添加@Autowired
,您并没有缩小任何范围,也没有向 Spring 提供任何额外的信息来帮助其做出决定——它的决定已经做出,因为只有一个候选人。
因此,为方便起见,Spring 团队决定 @Autowired
应该是可选的。由于它不帮助 Spring 框架做出决定,它的存在只是噪音。
如果您的组件有多个构造函数,那么您可以在其中一个上使用@Autowired
来告诉 Spring“使用这个,而不是那个”。
【讨论】:
很好的解释,完全有道理。谢谢。我只是创建了一个使用@Service 注释的服务类,并尝试执行自动装配服务 srv;在我的 Controller 类中,期望 Spring 能够让我获得该服务的 bean,假设它将使用 Default 构造函数实现。但相反,我需要提供无参数或参数化构造函数。以上是关于Spring 在没有 @Autowired 注释的构造函数中注入依赖项的主要内容,如果未能解决你的问题,请参考以下文章
Spring 注解之@Autowired、@Qualifer以及@Resource的区别
构造函数上的 Spring @Autowired 注释如何工作?
JUnit 在带有 @Autowired 注释的 Spring Boot 中不起作用
在spring security dofilter身份验证方法中使用@Autowired注释时出现Nullpointer异常[关闭]