Laravel 服务容器粗浅认知
简介
在讲解 服务容器 的初始化前,我们先要弄明白 服务容器 到底是个什么东东。
从数据类型本质上来说,Laravel 服务容器就是一个类,PHP 解析过程会被实例化为一个对象。我们都知道 PHP 实例化类要调用类的构造方法的,而这个执行构造方法的过程就是 服务容器的初始化。
从程序设计原则上看,Laravel 服务容器就是我们经常听到的 IoC/DI 容器,而且还是一个高级 IoC/DI 容器。
从程序设计模式上看,Laravel 服务容器可以看成 一棵树,一颗注册树。
IoC/DI 容器
IoC: Inversion of Control -- 控制反转
DI: Dependency Injection -- 依赖注入
控制反转、依赖注入,呵呵,多么高深、逼格高的两个词语。不得不吐槽,这种掩盖本质特征,给人一头雾水的词语,我真心不喜欢。当然我这是从初学者角度去看问题的,如果从创造这两个词语的大神角度去看,他该吐槽我了。
好了,简要讲明这两个词的含义:
控制反转是相对于控制正转来讲的,有反必有正。有光明必有黑暗,抛弃黑暗讲光明,就像抛弃女人讲男人,那还叫男人吗,应该叫大写的G,哈哈开个玩笑。
依赖注入是控制反转的另一面的说法,说的都是同一种现象。就如同:有人给我送礼物。对于我来说,是拿礼物;而对于他来说,是送礼物。本质上都在讲礼物一个传递过程。而控制反转就是拿礼物,依赖注入就是送礼物。
控制正转
class A
{
protected $b;
public function __construct()
{
$this->b = new B();
}
public function getB()
{
return $this->b;
}
}
class B
{
public function __construct(){}
}
$b = (new A)->getB();
var_dump($b);
上面,不难看出 new A 需要 new B。这种主动 new B 的现象就叫做控制正转
控制反转
class A
{
protected $ioc;
public function __construct(Ioc $ioc)
{
$this->ioc = $ioc;
}
public function getB()
{
return $this->ioc->make('b');
}
}
class Ioc
{
protected $instances = [];
public function __construct()
{
$this->instances['a'] = new A($this);
$this->instances['b'] = new B($this);
}
public function make(string $abstract)
{
return $this->instances[$abstract];
}
}
class B
{
protected $ioc;
public function __construct(Ioc $ioc)
{
$this->ioc = $ioc;
}
}
$ioc = new Ioc();
$a = $ioc->make('a');
$b = $a->getB();
var_dump($b);
如同上面这样,不需要在 A 中直接 new B。而是让 IoC 容器将 B 给我,这就叫控制反转。
依赖注入
控制反转是站在 A 的立场来看的,它是拿 B 的。
依赖注入是站在 IoC 的立场来看的,它是送 B 的。
注册树模式
Laravel 服务容器抽象点讲,如下打了一比方:
注册树模式不好形容,我们把这颗树换成一个大箱子。所有提供服务的实例对象,是这个大箱子里面的物品。且在 Laravel 中会对大箱子里面的物品进行分类。没做好的物品放到一类,并做好复杂标记;做好的物品放到一类,并做好唯一标记。
而当我们要使用没有做好的物品时,会对这个物品做最后加工,确保能用,才给我们用,并且把这个做好的归类到做好一类中,并把原先的复杂标记删掉。
当我们要是用做好的物品时,大箱子会直接给我们用。