我正在学习 Spring Boot 框架,我想了解 @Autowired
注释的工作原理。我知道在 Spring Boot 中我们有一个上下文,在那个上下文中有一些 bean,它们可以通过 @Autowired
注释相互连接,这是因为在 Spring Boot 中我们有依赖注入(inject),但是如何构造函数被调用了吗?
我有这样的服务:
@Service
public class MyService {
public MyService() {
// do something
}
}
在我的类里面:
public class MyClass {
@Autowired
MyService service;
}
问题是:
MyService
的构造函数是否被调用并执行了“do something”,或者它会调用一个空的构造函数,所以我不能依赖“do something”将被执行的事实?
最佳答案
长话短说
当创建 beans 时,Spring 必须调用目标 bean 类包含的构造函数:
- 如果没有定义构造函数 - 那么 Spring 将调用编译器生成的隐式默认构造函数。
- 如果没有显式定义无参数构造函数,那么 Spring 会调用这个构造函数,因为没有定义其他构造函数。
- 如果定义了一个构造函数,它需要一些依赖项,那么 Spring 将不得不调用它并为其提供依赖项。 (从 Spring 4.3 开始,您甚至不必使用
@Autowired
标记此构造函数)。 - 如果定义了多个 args 构造函数,那么您将不得不解决歧义,因为 Spring 将不知道选择哪一个。 (然后您可以使用
@Autowired
标记其中之一或使用配置类来定义您的 bean)。
旁注
Spring IOC container (应用程序上下文)负责保存 bean 并在需要时返回它们。要创建上下文,您必须告诉 Spring 在哪里查找 bean 定义:您可以提供 xml 文件、java 配置或启用给定包中组件的自动扫描。创建 Spring 上下文时,它必须创建 bean。它将尝试调用构造函数并为需要它们的 bean 提供任何依赖项。
在您的示例中,当将为上下文创建 MyClass
的实例时,它将调用 MyClass
类的默认构造函数,然后通过反射设置它的依赖项。
然而,字段注入(inject)通常不是一个好主意,因为您在测试此类组件时可能会遇到问题。构造函数或 setter 注入(inject)是更好的选择。
如果您将 MyClass
更改为:
public class MyClass {
private MyService service;
@Autowired
public MyClass(MyService service) {
this.service = service;
}
}
在这里您提供自己的构造函数 - 请注意,在这种情况下不会生成默认构造函数。因此 Spring 将不得不调用您提供的构造函数并满足它的依赖性。如果没有可以注入(inject)的依赖项 - 将抛出异常。
请注意,即使没有 Spring,您也可以使用您的类:
MyService myService = new MyService();
MyClass myclass = new MyClass(myService);
通过使用 Spring 构造型标记您的类并使用 @Autowired
,您只需启用 spring 对上下文创建和依赖注入(inject)的支持(在自动包扫描的情况下)
关于java - 使用@Autowired 调用构造函数如何工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56088861/