当前位置: 首页 > 面试题库 >

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

郏扬
2023-03-14
问题内容

我对使用Spring将对象注入到类中有疑问。我在项目中使用了以下代码:

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

然后通常在以下方法上使用它:

personRepository.save(p);

否则,我在Spring示例中发现了注入构造函数的情况:

private final PersonRepository personRepository;

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

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


问题答案:

tl; dr-构造函数注入是执行DI的最佳方法

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

细节

应该设计一种类型,以便您只能根据其创建处于有效状态的实例。为了实现这一目标,该类型的所有强制依赖 的需要
是构造函数的参数。这意味着,可以null检查这些依赖项,并将其分配给最终字段以促进不变性。除此之外,在处理代码时,对于该实例的调用者(或创建者),可以立即看出它必须提供哪些依赖项(通过浏览API文档或在IDE中使用代码完成功能)。

使用场注入无法实现所有这些功能。您不会从外部看到依赖关系, 需要使用
一些黑魔法来注入依赖关系,并且null除非您盲目地信任容器,否则您永远无法确保它们不是。

最后但并非最不重要的一个方面实际上是,使用字段注入,为类添加许多依赖关系会比较容易,这本身就是设计问题。对于构造函数来说,它在更早的时候就变得更加痛苦,这是
一件好事, 因为它告诉您有关类设计的一些信息:类承担太多的责任。首先无需计算指标,当您尝试扩展它时会感觉到。

货柜

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

  • 仅仅因为容器存在,并不意味着您必须将所有基本的面向对象的设计原则都抛在脑后,对吗?即使有止汗剂,您仍然要洗个澡,对吗?

  • 即使是设计用于容器的类型, 也将 手动使用:在单元测试中。如果您不编写单元测试,那么这是另一个主题。

  • 可以减轻所谓的附加构造函数的冗长性(“我可以用单行注入实现相同的功能!!”-“不,您不能。实际上您可以通过编写更多的代码来 获得 一些东西。”)通过龙目岛(Lombok)之类的东西。使用Spring和Lombok注入构造函数的组件如下所示:

    @Component
    

    @RequiredArgsConstructor
    class MyComponent implements MyComponentInterface {

    private final @NonNull MyDependency dependency;


    }

Lombok将负责生成一个构造函数,该构造函数为每个final字段采用一个参数,并null在分配给定参数之前检查给定参数。因此,您可以有效地获得现场注入的简短性和构造函数注入的设计优势。

结语

最近,我参加了与一些非Java人士的讨论,我对构造函数DI使用“注入”一词感到非常困惑。实际上,他们认为-这样做有很多道理-
通过构造函数传递依赖项根本不是注入,因为这是将对象传递给其他对象的最自然的方式(与各种注入形成鲜明对比)。

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

资源资源

  • 奥利弗·吉尔克(Oliver Gierke)-为什么电场注入是邪恶的
  • Jens Schauder-做依赖注入的一种正确方法


 类似资料:
  • 我对使用Spring向类注入对象有疑问。我在我的项目中使用了这样的代码: 然后通常在以下方法中使用: 否则,我在Spring示例中发现,注入构造函数: 所以这两个都是正确的?或者每一个都有它的属性和用法?

  • 我已经使用GoogleGuice几个月了。我对它很满意,但似乎我用错了。我创造了很多辅助注射,有时还有两个注射器。 因此,我想了解这里的一般原则。 是否应该为连接主类所有内容的所有应用程序配备一个喷油器? 最佳实践是关于从应用程序一开始就尝试在构造函数中注入大量内容吗?(我看到了测试的优势) 我的主要问题是,有时我觉得某些对象组的创建属于某个组件。有必要封装它吗?你会如何处理? 当您拥有一个重要的

  • 例如,Foos的资源可能如下所示: 对于酒吧:

  • 问题内容: 我的团队正在研究依赖项注入框架,并试图在使用Google-Guice和PicoContainer之间做出选择。 我们正在寻找框架中的几件事情: 较小的代码占用空间-我的意思是较小的代码占用空间是我们不想在我们的代码库中到处都有依赖项注入代码垃圾。如果我们需要在将来进行重构,我们希望它尽可能简单。 性能-创建和注入对象时,每个框架有多少开销? 易于使用-学习曲线是否很大?我们是否必须编写

  • 从零开始,没有任何以前的Jersey 1.x知识,我很难理解如何在我的Jersey 2.0项目中设置依赖注入。 我也知道HK2在Jersey 2.0中可用,但我似乎找不到有助于Jersey 2.0集成的文档。 我可以让容器启动并提供我的资源,但是当我将@inject添加到MyService时,框架就会抛出一个异常: 我的starter项目可在github:https://github.com/do

  • 我尝试用Spring-Boot创建一个spring web应用程序。我的第一个问题是依赖注入对我不起作用。这是我跟踪的那篇文章。 我创建了一个应用程序类: 我的分级文件: 我所期望的:当我打开/greeting页面时,将出现log,但我在的开头得到了这一点: 2017-09-12 10:47:56.058警告7545--[main]ConfigEmbeddedWebApplicationConte