什么是 DI 容器?

41

我正在观看一段关于依赖注入的课程视频,讲师提到了di-container,但没有详细解释,现在我读了一些文章,想确认一下我是否理解正确。以下是一个简单的程序,我的问题是:

下面的Program类是一种最简单的di-container吗?如果不是,那么最简单的di-container会是什么样子?

interface  Implementable {
    void doSmth();
}

class A implements Implementable {

    @Override
    public void doSmth() {

    }
}

class B {

    private Implementable i;

    public B(Implementable implementable) {
        this.i= implementable;
    }

    public void doSmth(){
        i.doSmth();
    }
}

这个类是 DI 容器吗?

class Program {
    B b = new B(new A());
    b.doSmth();
}

快速搜索得到了https://www.dotnettricks.com/learn/dependencyinjection/what-is-ioc-container-or-di-container。 - Nkosi
1
你混淆了术语。在这个上下文中,Program类是组合根,并且正在执行纯DI。 - Nkosi
1
这是关于该主题的另一篇非常有帮助的文章:http://blog.ploeh.dk/2014/06/10/pure-di/ - Nkosi
根据这篇文章http://fabien.potencier.org/do-you-need-a-dependency-injection-container.html,DI容器实例化和配置对象,这难道不是“Program”类正在做的吗? - Abdurakhmon
1个回答

52
根据《依赖注入原理、实践和模式》一书,DI容器是:
“一个软件库,提供DI功能,并允许自动化许多涉及对象组合、拦截和生命周期管理的任务。DI容器也被称为控制反转(IoC)容器。”(§3.2.2)
至少,DI容器允许自动装配,即:
“通过利用编译器和[其运行时环境]提供的类型元数据,自动从抽象和具体类型之间的映射中组合对象图。”(§12.1.2)
这通常意味着DI容器将分析类型的构造函数,并将依赖项注入其中,而无需手动指定每个构造函数参数。
从这个角度来看,你的Program类并不是一个DI容器,而是你的Program类充当了一个Composer的角色,它是组合根的一部分。一个组合根是:

"一个(最好是唯一的)应用程序中模块组合在一起的地方。"(§4.1)

Composer是组合根的一部分,它负责实际构建对象图。

"它是组合根的一个重要部分。Composer通常是一个DI容器,但也可以是任何手动构建对象图的方法"(§8)

在你特定的组合根中,你没有使用DI容器,而是使用纯DI的方式。
"不使用DI容器的DI应用实践。"(§1.1.1)
换句话说,纯DI是通过手动使用您所使用的编程语言的new关键字来组合对象图的实践,与使用DI容器相对立,就像您的Program类所展示的那样。
简单的DI容器会是什么样子?
DI容器的实现通常相当复杂,有很多构建方式。然而,它们的本质在于抽象和具体类型之间的映射。因此,大多数DI容器在内部使用字典或哈希映射。这个Stack Overflow答案展示了一个简单的基于字典的实现(使用C#),只需几行代码即可实现。

3
开始引用的书中提供了一些免费内容。作为一个试图理解依赖注入的人,这对我非常有帮助。链接为:https://freecontent.manning.com/dependency-injection-writing-maintainable-loosely-coupled-code/ - Brian
此外,该书的第一章可以在网上免费阅读。只需访问该书的主页并在目录中点击第一章即可。 - Steven

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接