浅谈Laravel中的设计模式(三) Container 容器

栏目: PHP · 发布时间: 6年前

内容简介:容器这个词估计使用过Laravel的童鞋们肯定不陌生了,但是日常业务开发好像都没见过它,我们今天就来看看他到底是干什么用的,本篇使用Laravel的精简版Lumen进行举例。首先他出现在哪里呢?我们可以从入口文件找到他,就是这个

容器这个词估计使用过 Laravel 的童鞋们肯定不陌生了,但是日常业务开发好像都没见过它,我们今天就来看看他到底是干什么用的,本篇使用Laravel的精简版 Lumen 进行举例。

首先他出现在哪里呢?

浅谈Laravel中的设计模式(三) Container 容器

我们可以从入口文件找到他,就是这个 $app ,那么这个 $app 到底是什么?我们继续深入看看

浅谈Laravel中的设计模式(三) Container 容器
浅谈Laravel中的设计模式(三) Container 容器

在app.php文件夹中可以看到,这个 $app 就是Laravel\Lumen\Application::class,而这个类继承了Container类,所以说Application类就是Laravel中的容器了。

“赵童鞋,究竟什么是容器呢?"

Laravel中的容器其实就是整个框架的核心,在上图的index.php中可以看到,一个Request进来后,index.php其实只是调用了 $app->run() 方法。

之后的URL解析、中间件处理、依赖注入,直到请求进入业务方法里,通通都是容器在进行处理。

二、容器是怎么运作的呢?

像上述所说,Laravel框架中的大部分功能都是在容器中实现的,而最常用的功能就有服务提供者。

我们这里就通过调用DB的Facade类来说明一下容器中的服务提供者是怎么运作的。

浅谈Laravel中的设计模式(三) Container 容器

首先可以看到,在Application中,"db" 绑定了 registerDatabaseBindings() 这个方法。

浅谈Laravel中的设计模式(三) Container 容器

registerDatabaseBindings() 方法中,使用了框架提供的 singleton() 注册了一个关联“db”的匿名函数,而这个匿名函数就是“db”的解析器。

在前面的篇章我们讲到,当我们通过静态调用DB类的时候,Laravel的Facade模式就通过调用 resolveFacadeInstance() 去容器中解析出“db”的实际对象。

浅谈Laravel中的设计模式(三) Container 容器
可以看到,里面的实际操作是使用了 static::$app[$name]

的写法去获取。

因为Laravel中的Container实现了ArrayAccess,所以实际调用会进入到Container的 offsetGet() 方法中,也就是进入了 make() 方法,而因为容器的实际对象是Application类,所以会先进入Application的 make() 方法。

浅谈Laravel中的设计模式(三) Container 容器
浅谈Laravel中的设计模式(三) Container 容器

在make方法中,终于出现了前面说到的 $availableBindings ,也就是说,在这里会调用前面的 registerDatabaseBindings() 方法,注册“db”的解析器。再进行调用父类,也就是Container的 make() 方法。

浅谈Laravel中的设计模式(三) Container 容器

而make()方法又跳进了 resolve() 中。

(不得不说,当初第一次看框架代码时我也被绕晕了,习惯就好)

浅谈Laravel中的设计模式(三) Container 容器

resolve() 这里,容器会先去 $this->instances 中查找,也就是一个用于存放已实例化的对象的数组。

当获取不到的时候,就会通过 $this->getConcrete() 获取到我们前面注册的“db”的解析器,也就是调用文章最前面 registerDatabaseBindings() 中的匿名函数,获取到“db”的实例,最终返回给前面的DB静态调用。

(至于匿名函数解析器是怎么工作的,感兴趣的童鞋可以去看看官方文档的loadComponent、register流程,亲自去看一遍源码印象更深刻)

三、容器有什么用呢?

通过上面的描述,我们可以知道容器中是有一个数组 instances[] 保存着已实例化了的对象的,也就是单例模式。

而没有实例化的对象也是有着类似于解析器之类的关联机制。

这种做法最大的好处就是可以减少对象生成的开销,例如某个接口需要使用到 Redis 和DB,那么框架就会去调用解析器将这两个对象解析出来,并且保存在数组中以便于后续的逻辑中进行复用。

而当某个接口不需要Redis和DB的时候,就可以节省下这两个对象的开销,并不需要修改一句代码。

四、结语

本次的浅谈容器到这里就结束了,如果觉得被绕晕了的话,说明真的认真看了o( ̄▽ ̄)d。

千万别灰心,亲自去跟着源码走一趟,这种被绕晕的感觉就会慢慢消失了。

----- End -----

更多好文

请扫描下面二维码

欢迎关注~

浅谈Laravel中的设计模式(三) Container 容器

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Bandit Algorithms for Website Optimization

Bandit Algorithms for Website Optimization

John Myles White / O'Reilly Media / 2013-1-3 / USD 19.99

This book shows you how to run experiments on your website using A/B testing - and then takes you a huge step further by introducing you to bandit algorithms for website optimization. Author John Myle......一起来看看 《Bandit Algorithms for Website Optimization》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具