本篇文章给你们带来的内容是关于Laravel服务容器的绑定与解析,有必定的参考价值,有须要的朋友能够参考一下,但愿对你有所帮助。php
前言laravel
老实说,第一次老大让我看laravel框架手册的那天早上,我是很绝望的,由于真的没接触过,对我这种渣渣来讲,laravel的入门门槛确实有点高了,但仍是得硬着头皮看下去(虽然到如今我还有不少没看懂,也没用过)。
后面慢慢根据公司项目的代码对laravel也慢慢熟悉起来了,但仍是停留在一些表面的功能,例如依赖注入,ORM操做,用户认证这些和我项目业务逻辑相关的操做,而后对于一些架构基础的,例如服务提供器,服务容器,中间件,Redis等这些一开始就要设置好的东西,我却是没实际操做过(由于老大一开始就作好了),因此看手册仍是有点懵。
因此有空的时候逛逛论坛,搜下Google就发现许多关于laravel核心架构的介绍,以及如何使用的网站(确实看完后再去看手册就好理解多了),下面就根据一个我以为不错的网站上面的教学来记录一下laravel核心架构的学习
网站地址:https://laraweb.net/ 这是一个日本的网站,我以为挺适合新手的,内容用浏览器翻译过来就ok了,毕竟日文直翻过来很好理解的web
关于服务容器数据库
手册上是这样介绍的:Laravel 服务容器是用于管理类的依赖和执行依赖注入的工具。依赖注入这个花俏名词实质上是指:类的依赖项经过构造函数,或者某些状况下经过「setter」方法「注入」到类中。。。。。。(真的看不懂啥意思)
服务容器是用于管理类(服务)的实例化的机制。直接看看服务容器怎么用bootstrap
1.在服务容器中注册类(bind)数组
1浏览器 2缓存 |
|
2.从服务容器生成类(make)
1 2 3 |
|
这是服务容器最简单的使用,下面是对服务容器的详细介绍
laravel容器基本认识
一开始,index.php 文件加载 Composer 生成定义的自动加载器,而后从 bootstrap/app.php 脚本中检索 Laravel 应用程序的实例。Laravel 自己采起的第一个动做是建立一个 application/ service container 的实例。
1 2 3 |
|
这个文件在每一次请求到达laravel框架都会执行,所建立的$app便是laravel框架的应用程序实例,它在整个请求生命周期都是惟一的。laravel提供了不少服务,包括认证,数据库,缓存,消息队列等等,$app做为一个容器管理工具,负责几乎全部服务组件的实例化以及实例的生命周期管理。当须要一个服务类来完成某个功能的时候,仅须要经过容器解析出该类型的一个实例便可。从最终的使用方式来看,laravel容器对服务实例的管理主要包括如下几个方面:
服务的绑定与解析
服务提供者的管理
别名的做用
依赖注入
先了解如何在代码中获取到容器实例,再学习上面四个关键
第一种是
1 2 3 4 |
|
第二种是
1 2 3 4 5 6 7 |
|
第三种是
在服务提供者里面直接使用$this->app。服务提供者后面还会介绍,如今只是引入。由于服务提供者类都是由laravel容器实例化的,这些类都继承自Illuminate\Support\ServiceProvider,它定义了一个实例属性$app:
1 2 3 |
|
laravel在实例化服务提供者的时候,会把laravel容器实例注入到这个$app上面。因此咱们在服务提供者里面,始终能经过$this->$app访问到laravel容器实例,而不须要再使用app()函数或者App Facade了。
浅义层面理解,容器既然用来存储对象,那么就要有一个对象存入跟对象取出的过程。这个对象存入跟对象取出的过程在laravel里面称为服务的绑定与解析。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
|
还有一个单例绑定singleton,是bind的一种特殊状况(第三个参数为true),绑定到容器的对象只会被解析一次,以后的调用都返回相同的实例
1 2 3 4 |
|
在绑定的时候,咱们能够直接绑定已经初始化好的数据(基本类型、数组、对象实例),还能够用匿名函数来绑定。用匿名函数的好处在于,这个服务绑定到容器之后,并不会当即产生服务最终的对象,只有在这个服务解析的时候,匿名函数才会执行,此时才会产生这个服务对应的服务实例。
实际上,当咱们使用singleton,bind方法以及数组形式,(这三个方法是后面要介绍的绑定的方法),进行服务绑定的时候,若是绑定的服务形式,不是一个匿名函数,也会在laravel内部用一个匿名函数包装起来,这样的话, 不轮绑定什么内容,都能作到前面介绍的懒初始化的功能,这对于容器的性能是有好处的。这个能够从bind的源码中看到一些细节:
1 2 3 |
|
看看bind的底层代码
1 |
|
第一个参数服务绑定名称,第二个参数服务绑定的结果(也就是闭包,获得实例),第三个参数就表示这个服务是否在屡次解析的时候,始终返回第一次解析出的实例(也就是单例绑定singleton)。
服务绑定还能够经过数组的方式:
1 2 3 |
|
绑定大概就这些,接下来看解析,也就是取出来用
1 |
|
这个方法接收两个参数,第一个是服务的绑定名称和服务绑定名称的别名,若是是别名,那么就会根据服务绑定名称的别名配置,找到最终的服务绑定名称,而后进行解析;第二个参数是一个数组,最终会传递给服务绑定产生的闭包。
看源码:
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 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
|
第一步:
1 2 3 |
|
该方法主要是区分,解析的对象是否有参数,若是有参数,还须要对参数作进一步的分析,由于传入的参数,也多是依赖注入的,因此还须要对传入的参数进行解析;这个后面再分析。
第二步:
1 2 3 |
|
若是是绑定的单例,而且不须要上面的参数依赖。咱们就能够直接返回 $this->instances[$abstract]。
第三步:
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 |
|
这一步主要是先从绑定的上下文找,是否是能够找到绑定类;若是没有,则再从 $bindings[] 中找关联的实现类;最后尚未找到的话,就直接返回 $abstract 自己。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
|
若是以前找到的 $concrete 返回的是 $abstract 值,或者 $concrete 是个闭包,则执行 $this->build($concrete),不然,表示存在嵌套依赖的状况,则采用递归的方法执行 $this->make($concrete),直到全部的都解析完为止。
$this->build($concrete)
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 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
|