浅谈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 容器

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

查看所有标签

猜你喜欢:

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

思考的技术

思考的技术

[日]大前研一 / 刘锦秀、谢育容 / 中信出版社 / 2010-11 / 32.00元

思路决定出路,没有了思路,也就没有了出路。 在充满危机与冒险的当下,我们缺乏的不是技巧而是揭发事务本质的动力和好奇心,缺少怀疑一切的心态和对固有模式的怠惰。 大前研一凭借他30多年的管理咨询经验,为我们提供了一种全新的可借鉴的思考方式。 企业和个人惟有改变既有的思考模式,放弃对过去成功经验的迷恋,学习有创意的思考方法,方能找到正确的经营思路。一起来看看 《思考的技术》 这本书的介绍吧!

随机密码生成器
随机密码生成器

多种字符组合密码

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码