gpt4 book ai didi

spring - Field @Autowired 背后的魔力是什么

转载 作者:行者123 更新时间:2023-12-04 23:44:33 24 4
gpt4 key购买 nike

我目前正在提高我的 Spring 知识。我想知道当我在字段上使用 Spring 注释 @Autowire 时会发生什么。

这是一段代码:

输出助手文件

@Component
public class OutputHelper {
@Autowired
@Qualifier("csvOutputGenerator")
private IOutputGenerator outputGenerator;

public void setOutputGenerator(IOutputGenerator outputGenerator) {
this.outputGenerator = outputGenerator;
}

// I can focus only on what my code do because my objects are injected
public void generateOutput(){
outputGenerator.generateOutput();
}
}

CsvOutputGenerator 文件
@Component 
public class CsvOutputGenerator implements IOutputGenerator {
public void generateOutput(){
System.out.println("Csv Output Generator");
}
}

申请文件
public static void main(String[] args) {
// Create the spring context
ApplicationContext context = new ClassPathXmlApplicationContext("META-INF/spring/spring-module.xml");

// Get the configured OutpuHelper from the spring-module.xml
OutputHelper output = (OutputHelper) context.getBean("outputHelper");

// Display output from the output configured
output.generateOutput();
}

我的配置文件只包含 <context:component-scan base-package="com.xxx.xxx.output"/>
当我执行此代码时,一切正常。但是让我感到惊讶的是,当我删除 OutPutHelper 文件中的 setOutputGenerator 时,我的代码仍然可以正常工作。我坚信使用这种配置,OutputHelper 首先是使用默认构造函数创建的,并使用 setter 进行初始化。

我预计会出现错误,因为无法初始化变量 outputGenerator。

有人可以帮我理解吗?

最佳答案

拥有字段的想法@Autowired是有问题的。它有效,但它会使您的实现的其他方面(即测试)变得困难。

有3种类型的注入(inject):

  • 字段 - 基本上配置将反射( Field.set(Object, Object) )直接应用于字段:
    @Autowired
    private MyInterface field;
  • setters - 使用这种方法,每个依赖项的配置都通过一个属性(spring 遍历所有方法并使用 Method.invoke(Object, Object...) 执行每个使用 @Autowired 注释的方法,因此其值使用其 setter 配置如下:
    @Autowired
    public void setField(MyInterface value) {
    this.field = value;
    }
  • 构造函数——最后一个也是我更喜欢的方法,构造函数注入(inject)。那个基本上用 @Autowired 注释构造函数您可以直接在构造函数上配置 bean,而不是使用方法或字段。因为那个 spring 将选择一个构造函数来实例化你的 @Component ,它将使用 @Autowired如果存在或为空的 params 构造函数,则使用 Constructor.newInstance(Object...) 调用它.例子:
    @Component
    public class Implementation {
    private MyInterface field;
    @Autowired
    public Implementation(MyInterface value) {
    Assert.notNull(value, "value should not be null");
    this.field = value;
    }
    }

  • 控制反转(或依赖注入(inject))背后的一个想法是能够隔离一段代码,以便提供体面的测试实现支持。

    为了更深入,有必要评论一下,在单元测试期间,您希望该类处于其隔离形式,您将与该类一起使用的所有内容基本上都是对其依赖项(注入(inject))的模拟。

    那么,结果如何:
  • 如果你这样做 现场注入(inject) ,每次在测试期间使用一些反射来配置 bean 将非常昂贵(需要引入另一个逻辑来配置要测试的 bean)。
  • setter 注入(inject)方法 您将能够使用自己的 bean 来配置它,并使用必要的模拟来隔离您的实现并测试其功能。
  • 最后,使用 构造函数注入(inject) 方法您不仅将获得配置 bean 的支持,而且您将能够要求它的依赖项。这意味着对于每个新的依赖项,都会在构造函数中添加一个新参数,这会给您带来开发时间的优势,例如,您将能够在开发时间看到单元测试因引入该新依赖项而受到影响(一次您的 IDE 会为您指出)。
  • 关于spring - Field @Autowired 背后的魔力是什么,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31766028/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com