Symfony:自动装配解决了什么问题?

Symfony: what does autowiring solve?

如果我错了请纠正我 - Symfony 自动装配允许程序员通过类型提示自动获取服务实例作为函数的参数。

所以不用打字(例如)

public function dostuff() {
  $stuff = StuffGenerator::getInstance();
  $stuff->do();
}

我现在可以打字了

public function dostuff(StuffGenerator $stuff) {
  $stuff->do();
}

然后 相信 $stuff 是好的。就这些了吗?

我还是比较喜欢第一种方法。我倾向于尽可能避免自动装配。我一直在阅读它,但到目前为止,没有什么能说服我将我的应用程序逻辑移交给更高的权力,然后我必须配置它,或者更糟的是,只是相信它,是 good 想法。

一方面,它降低了代码的可移植性。

我错过了什么?是否存在我无法避免自动装配的情况,因为它解决了一些我不知道的独特问题?

这类问题通常不适合 Whosebug,但 "what does autowiring solve" 可以回答。

首先要意识到问题中的示例与一般的自动装配或依赖注入无关。

public function dostuff(StuffGenerator $stuff) {
  $stuff->do();
}

上面例子的含义是某种神秘的力量正在将东西直接注入到方法中,而这些方法又立即作用于它们。好吧,不。 Autowire 不会这样做。而且我当然不希望使用谁知道在哪里的参数来调用方法。

所以让我们重写这个例子:

class MyClass {
    private $stuff;
    public function __construct(StuffGenerator $stuff) {
        $this->stuff = $stuff;
    }
    public function doStuff() {
        $this->stuff->do();
    }
}

几乎在所有情况下,依赖项都被注入到构造函数中,然后存储为成员变量。 class 的其余部分没有什么神秘的事情发生。您可以争论注入 $stuff 还是让构造函数从单例访问 $stuff。我不会在这里讨论这个论点,因为它基本上与自动装配无关。

要使上面的 MyClass 示例使用 Symfony 容器工作,需要容器知道需要哪些依赖项。回到自动装配之前的旧时代(3.1 左右之前),开发人员必须手动定义每个服务。类似于:

# app/config/services.yml
services:
    app.stuff_generator:
        class App\StuffGenerator
    app.myclass:
        class: App\MyClass
            arguments:
                - '@app.stuff_generator'

这并不难,但随着服务数量的增加,服务文件的大小也随之增加。就像回忆往事一样,here 是我的一个 S2.x 应用程序的大约 6 个不同服务定义文件之一。将所有定义放在一个地方实际上是一种很好的选择。使查看事物的连接方式变得更加容易。但这确实很乏味。

那么现在我们来谈谈真正的问题。假设您接受将依赖注入与服务容器结合使用的概念,那么自动装配会简化在容器中定义服务的过程。对于 MyClass 示例,假设只有一个 StuffGenerator 实例浮动,则根本不需要手动服务配置。当然,你会 运行 进入需要手动定义的缩放器依赖项之类的东西。但是,成百上千行的配置仍然可以减少到几十行。

这就是 autowire 解决的问题。