Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/398.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用@Autowired的构造函数调用如何工作?_Java_Spring_Spring Boot - Fatal编程技术网

Java 使用@Autowired的构造函数调用如何工作?

Java 使用@Autowired的构造函数调用如何工作?,java,spring,spring-boot,Java,Spring,Spring Boot,我正在学习Spring Boot框架,我想了解@Autowired注释是如何工作的。我知道在Spring Boot中我们有一个上下文,在该上下文中有一些bean可以通过@Autowired注释相互连接,这是因为在Spring Boot中我们有依赖项注入,但是构造函数是如何调用的 我有这样的服务: @Service public class MyService { public MyService() { // do something } } 在一节课上,我

我正在学习Spring Boot框架,我想了解
@Autowired
注释是如何工作的。我知道在Spring Boot中我们有一个上下文,在该上下文中有一些bean可以通过
@Autowired
注释相互连接,这是因为在Spring Boot中我们有依赖项注入,但是构造函数是如何调用的

我有这样的服务:

@Service
public class MyService {

    public MyService() {
        // do something
    }

}
在一节课上,我有:

public class MyClass {

    @Autowired
    MyService service;

}
问题是:

是调用了MyService的构造函数并执行了“do something”还是调用了空构造函数,因此我不能依赖执行“do something”的事实?

TL;博士 创建bean时,Spring必须调用目标bean类包含的构造函数:

  • 如果没有定义构造函数,那么Spring将调用编译器生成的隐式默认构造函数
  • 如果没有显式定义args构造函数,那么Spring将调用这个构造函数,因为没有定义其他构造函数
  • 如果定义了一个构造函数,它需要一些依赖项,那么Spring必须调用这个构造函数并为它提供依赖项。(从Spring4.3开始,您甚至不必使用
    @Autowired
    标记此构造函数)
  • 若定义了多个args构造函数,那个么您必须解决歧义,因为Spring不知道选择哪一个。(然后可以使用
    @Autowired
    标记其中一个,或者使用配置类定义bean)
  • 旁注 (应用程序上下文)负责保存bean并在需要时返回它们。要创建上下文,您必须告诉Spring在何处查找bean定义:您可以提供xml文件、java配置或启用给定包中组件的自动扫描。当创建Spring上下文时,它必须创建bean。它将尝试调用构造函数,并为需要它们的bean提供任何依赖项

    在您的示例中,当为上下文创建
    MyClass
    的实例时,它将调用
    MyClass
    类的默认构造函数,然后通过反射设置它的依赖关系

    然而,现场注入通常是一个坏主意,因为您在测试此类组件时可能会遇到问题。构造函数或setter注入是更好的选择

    如果您将
    MyClass
    更改为:

    public class MyClass {
    
        private MyService service;
    
        @Autowired
        public MyClass(MyService service) {
            this.service = service;
        }
    
    }
    
    这里您提供了自己的构造函数-注意,在这种情况下不会生成默认构造函数。所以Spring必须调用您提供的构造函数并满足它的依赖性。如果没有可以注入的依赖项,将抛出异常

    请注意,即使没有Spring,您也可以使用您的类:

    MyService myService = new MyService();
    MyClass myclass = new MyClass(myService);
    
    通过使用Spring原型标记您的类,并使用
    @Autowired
    您只需启用Spring对上下文创建和依赖项注入的支持(在自动包扫描的情况下)

    因为MyService有一个@Service注释,Spring将自动实例化它(即将其注册为bean)

    在创建它时,它扫描类的构造函数,发现定义了一个无参数构造函数,这是它将使用的唯一构造函数

    由于它通过调用找到的no args构造函数来创建服务,因此将执行位于“//do something”位置的代码

    另一方面,如果不添加此构造函数,MyService类将隐式定义一个空的非args构造函数,因此Spring将使用空构造函数。但是在您的例子中,您已经定义了一个显式构造函数(它覆盖了隐式的空no-args构造函数),因此Spring将其视为唯一可用的构造函数,并且没有歧义

    长话短说->如果定义了一个构造函数,Spring将始终自动使用它来创建bean

    附言:如果你使用@Autowired注释,你也可以有一个带参数的构造函数。在这种情况下,Spring将调用此构造函数来创建bean,并传递所需的参数(如果已声明此类bean可以自动连接到构造函数中)。

    长话短说

    Spring将使用默认构造函数(无参数构造函数)来构造组件。 在你的例子中

    @Service
    public class MyService {
    
    public MyService() {
       // do something
    }
    }
    
    将调用构造函数并调用
    //do something

    但是,请记住,如果您在类中添加了非默认构造函数(带参数的构造函数),那么编译器将不会为您生成默认构造函数,在这种情况下,spring将无法实例化您的
    MyService

    比如说

      @Service
        public class MyService {
    
        public MyService(String var) {
           // do something
        }
        }
    
    将抛出异常
    com.example.MyService
    中构造函数的参数0需要一个类型为“
    java.lang.String
    ”的bean,但找不到该bean。

    您的问题实际上与Spring无关。您可以决定如何构造
    MyService
    类。当您提供匹配的构造函数时,Spring将调用它,如果不能,则调用失败。Spring可以为一个类“发明”自己的构造函数并使用它。你试过调试或只是在构造函数中打印吗?@Tom我认为这是相关的,因为我有Spring注释和Spring上下文。@daniu,这是一个理论问题,我想检索更多的InfossSpring注释,Spring上下文并没有那么重要。Spring无法更改Java规则,因此您可以通过决定提供哪些构造函数来决定Spring如何创建bean。感谢您的回答,我知道它只是启用了支持,但我想学习如何使用Spring和Spring哲学:)请注意,从Spring 4.3版开始,可以省略构造函数上的Autowired annotation。“调用构造函数”应为“调用构造函数”