gpt4 book ai didi

java - 如何正确地进行依赖注入(inject)(在 Spring 中)?

转载 作者:IT老高 更新时间:2023-10-28 13:46:38 24 4
gpt4 key购买 nike

我对使用 Spring 将对象注入(inject)类有疑问。我在我的项目中使用了这种代码:

@Resource // or @Autowired even @Inject
private PersonRepository personRepository;

然后在方法上正常使用它:

personRepository.save(p);

否则我在 Spring 示例中找到,注入(inject)构造函数:

private final PersonRepository personRepository;

@Autowired
public PersonController(PersonRepository personRepository) {
this.personRepository = personRepository;
}

所以两者都是正确的?还是每个都有其属性和用途?

最佳答案

tl;dr - 构造函数注入(inject)是进行 DI 的最佳方式

后者是正确的,这不是因为 Spring 或任何依赖注入(inject)容器,而是面向对象的类设计原则。

详情

应该设计一个类型,以便您只能从中创建处于有效状态的实例。为了实现这一点,该类型的所有强制依赖项需要是构造函数参数。这意味着,可以检查这些依赖项null,分配给最终字段以提高不变性。除此之外,在使用代码时,对于该实例的调用者(或创建者)来说,它必须提供哪些依赖项是显而易见的(通过浏览 API 文档或使用 IDE 中的代码完成)。

所有这一切都无法通过现场注入(inject)实现。您从外部看不到依赖项,您需要一些黑魔法来注入(inject)依赖项,并且您永远无法确定它们不是 null 除非您盲目相信容器。

最后但并非最不重要的方面实际上是,通过字段注入(inject),向您的类添加大量依赖项并不那么痛苦,这本身就是一个设计问题。构造函数在更早的时候变得更加痛苦,这是一件好事,因为它告诉你一些关于你的类设计的事情:类有太多的责任。一开始不需要计算指标,当你尝试扩展它时你会感觉到它。

容器

人们经常争辩说这只是学术胡说八道,因为无论如何您都可以依赖容器。这是我对此的看法:

  • 仅仅因为存在容器,并不意味着您必须放弃所有基本的面向对象设计原则,对吗?即使有止汗剂,你还是要洗澡,对吧?

  • 即使是为容器设计的类型,也会手动使用:在单元测试中。如果你不写单元测试……那是另一个话题了。

  • 所谓的额外构造函数的冗长(“我可以通过单行字段注入(inject)实现同样的事情!!” - “不,你不能。你实际上 get 东西多写一行代码。”)可以通过 Lombok 之类的东西来缓解。 .使用 Spring 和 Lombok 的构造函数注入(inject)组件如下所示:

    @Component
    @RequiredArgsConstructor
    class MyComponent implements MyComponentInterface {

    private final @NonNull MyDependency dependency;


    }

Lombok 将负责为每个最终字段生成一个构造函数,并在分配之前检查给定参数的 null。所以你有效地获得了字段注入(inject)的简洁性和构造函数注入(inject)的设计优势。

结语

我最近参与了与一些非 Java 人员的讨论,我对构造函数 DI 使用术语“注入(inject)”感到非常困惑。实际上,他们争辩说——这有很多道理——通过构造函数传递依赖项根本不是注入(inject),因为这是将对象传递给其他对象的最自然的方式(与任何形式的注入(inject)形成鲜明对比)。

也许我们应该为这种风格创造一个不同的术语?也许是依赖喂养?

资源

关于java - 如何正确地进行依赖注入(inject)(在 Spring 中)?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24337486/

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