java - 使用@Autowired 调用构造函数如何工作?

标签 java spring spring-boot

我正在学习 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 类包含的构造函数:

  1. 如果没有定义构造函数 - 那么 Spring 将调用编译器生成的隐式默认构造函数。
  2. 如果没有显式定义无参数构造函数,那么 Spring 会调用这个构造函数,因为没有定义其他构造函数。
  3. 如果定义了一个构造函数,它需要一些依赖项,那么 Spring 将不得不调用它并为其提供依赖项。 (从 Spring 4.3 开始,您甚至不必使用 @Autowired 标记此构造函数)。
  4. 如果定义了多个 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/

相关文章:

java - 使用 Eclipse 导出 Java 游戏不起作用

Spring Boot 测试 : exception in REST controller

java - Spring 启动: ReentrantLock

spring-boot - 如何在 Spring Boot 版本中查找 spring 项目的版本

java - Spring Boot 配置是否带有预设默认值?

java - 内联字段初始化与构建器哪个更好

java - 无法创建任务或输入translate-classpath

java - Spring Boot自动创建数据库表

java - 使用接口(interface)重写方法

java - 如何在 spring boot 中使用非密码保护 (.p12) ssl 证书