Laravel 中的 IoC Container

概述

IoC(Inversion of Control)。

把依赖的注入交给容器控制。即为控制反转。

IoC(Inversion of Control)

Laravel 中的容器

容器即为:容纳了很多内容(很多层或者组件,包括 Routing,Validation 等很多很多)的一个对象。

在 Laravel 中,下面的 $app 就是容器。

1
2
3
4
5
Route::get('/', function()
{
$app = app();
var_dump($app);
});

浏览器中打印了大量内容。这个对象是 Illuminate\Foundation\Application 的实例,它包含了 Laravel 框架的所有组件。类 Application 扩展了类 Container

Container 实现了接口 ArrayAccess,意味着访问数据时具有灵活性。例如,以下两种语法获得的结果相同:

1
2
$foo->bar = "baz";
$foo['bar'] = "baz";

依赖注入

单纯的依赖注入是不可取的,因为要手动实例化并传入依赖,但有了 IoC Container 就不一样了。

在代码中是怎么工作的呢?

绑定类 Car 到容器中

用类 Container 中的方法 bind 把类 Car 绑定到 Container

1
2
3
4
5
6
7
8
9
10
11
12
class Car{}

App::bind('Car', function()
{
return new Car;
});

Route::get('/', function()
{
dd(App::make('Car')); // resolve it
});
// Car {#1521}

可以看到,我们用 make 方法从容器中取出了 Car

让 Car 依赖于 Tire 和 Engine

这种情况要怎么绑定 Car 对象呢?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
class Car {
protected $tire;
protected $engine;
public function __construct(Tire $tire, Engine $engine) {
$this->tire = $tire;
$this->engine = $engine;
}
}

class Tire {}

class Engine {}

App::bind('Car', function()
{
return new Car(new Tire, new Engine);
});


Route::get('/', function()
{
dd(App::make('Car')); // resolve it
});
// Car {#1521 ▼
// #tire: Tire {#1532}
// #engine: Engine {#1533}
// }

我们在绑定 Car 到容器中时,手动实例化了依赖的 TireEngine`。

如果把依赖处理交给 Container 呢?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Car {
protected $tire;
protected $engine;
public function __construct(Tire $tire, Engine $engine) {
$this->tire = $tire;
$this->engine = $engine;
}
}

class Tire {}

class Engine {}

Route::get('/', function()
{
dd(App::make('Car')); // resolve it
});
// Car {#1535 ▼
// #tire: Tire {#1536}
// #engine: Engine {#1537}
// }

这次没有手动绑定,而且也没有手动创建依赖并传入。但是仍然可以顺利获取到 Car

Laravel 做了什么?

  • 代码中是否专门绑定了 Car,如果有 _bing_,就是使用这个类?
  • 如果代码中没有绑定 Car?那就需要用到类反射,检测依赖项。
  • 解决 Car 所需的依赖(TireEngine)。
  • 创建包括了任何依赖项的新实例,搞定!

总结

这就是 IoC 容器的用途——它使设置依赖注入的任务变得更加容易。



Laravel 中的 IoC Container
https://hutaoren.cn/2021/10/14/Laravel 中的 IOC Container/
作者
胡桃仁
发布于
2021年10月14日
许可协议