symfony - Symfony: what does autowiring solve?
问题描述
Correct me if I'm wrong - Symfony autowiring allows a programmer to automagically get an instance of a Service as an argument to a function by typehinting that argument.
So instead of typing (for example)
public function dostuff() {
$stuff = StuffGenerator::getInstance();
$stuff->do();
}
I can now type
public function dostuff(StuffGenerator $stuff) {
$stuff->do();
}
and then just trust $stuff is good. Is that all ?
I still prefer the first method. I am inclined to avoid autowiring as much as possible. I've been reading up on it, but sofar nothing has convinced me handing over my app logic to a higher power, which I then have to configure, or worse, just trust it, is a good idea.
For one thing, it makes your code less portable.
What am I missing ? Are there situations where I can not avoid autowiring, because it solves some unique problem I am not aware of ?
解决方案
These sorts of questions are usually not a good fit for stackoverflow but "what does autowiring solve" can be answered.
First thing to realize is that the example in the question has nothing to do with autowiring or dependency injection in general.
public function dostuff(StuffGenerator $stuff) {
$stuff->do();
}
The implication of the above example is that some mysterious force is injecting stuff directly into methods which in turn immediately acts upon them. Well no. Autowire does not do this. And I certainly would not want methods being called with arguments from who knows where.
So lets rewrite the example:
class MyClass {
private $stuff;
public function __construct(StuffGenerator $stuff) {
$this->stuff = $stuff;
}
public function doStuff() {
$this->stuff->do();
}
}
In almost all cases, dependencies are injected into constructors and then stored as member variables. Nothing mysterious going on in the rest of the class. You can argue about injecting $stuff vs having the constructor accessing $stuff from say a singleton. I won't get into that argument here as it is basically off topic with respect to autowire.
For the above MyClass example to work using the Symfony container requires that the container be aware of what dependencies are needed. Back in the old pre-autowire days (prior to 3.1 or so), a developer had to manually define each service. Something like:
# app/config/services.yml
services:
app.stuff_generator:
class App\StuffGenerator
app.myclass:
class: App\MyClass
arguments:
- '@app.stuff_generator'
Not hard to do but as the number of services grew so did the size of the services file. Just as a trip down memory lane, here is one of about 6 different service definition files for one of my S2.x apps. It was actually kind of nice having all the definitions in one place. Made it easier to see how things were wired up. But it definitely got tedious.
So now we come to the actual question. Assuming that you buy into the notion of using dependency injection in combination with a service container, then autowire simplifies the process of defining your services in your container. For the MyClass example, no manual service configuration is needed at all assuming there is only one StuffGenerator instance floating around. And of course you will run into things like scaler dependencies that require manual definitions. But still, hundreds and hundreds of lines of configuration can be reduced to perhaps a few dozen.
And that is what autowire solves.
推荐阅读
- python - 解析一个选项卡式树文本文件并在 Pygtk 中创建一个 Treeview
- vue.js - 使用 npm 从 Git 安装 Bootstrap-Vue
- c - 运算符 '>>' 和 '&' 的非法操作数 (MISRA C)
- wpf - 尝试在 Visual Studio 2017 中查看应用程序属性页面时出错
- sql - 使用sql server从数据库中选择值到另一个
- javascript - React 如何向现有状态添加新的动态密钥?
- python - 估计加载图像数据集可能使用多少 RAM
- reactjs - 将位置提交到服务器后,React-native post 方法 API 不显示任何数据
- outlook - 有什么方法可以使用 Microsoft API 在会议室中添加和获取设备?
- mysql - 在mysql中优化查询更有效