您的位置:首页 > 编程语言 > PHP开发

laravel的模块化是如何实现的

2016-03-21 00:05 525 查看

laravel的模块化是如何实现的

在laravel提供的官方文档上,有一个这样的名词 服务提供者,文档中介绍了它在laravel框架中的角色,以及如何使用它,但却没有讲明服务提供者的本质--它是为了解决什么问题而存在的? 不解决这一点,对于它的理解,则只会停留在表面.服务提供者是laravel实现模块化设计的手法.

为什么要进行模块化设计这里就不说的,可以参考下这些:模块化设计 , 模块化的意义何在?

为了实现模块化,必然要将一段程序组合起来,完成特定的事,从而形成模块.在
laravel
中, 一个模块都表现为一个
Service
.应用程序主体与组件(模块)之间必然要通过某种方式连接起来,才能使组件被主体所调用.在laravel中一个
Service
会被它的
Service Prorider
注入到ioc中,这样组件就与主体联系了起来, 具体的表现形式则是组件被主体所用,主体使用组件完成组件所擅长的事. 源代码是最好的文档,接下来,我们就看看"文档"是怎么说的.

laravel的启动过程

我们从启动开始,详细地分析在整个应用程序的生命周期中,
Service Provider
到底是什么?通过阅读源码方式来了解
Serivce Provider
在laravel中到底做了什么.

laravle的启动过程做了很多事,这里就不一一叙述了,主要说明有关
Sevice Provider
的部分.laravel有两个入口分别处理不同的请求1:
public/index.php(http)
2.
php arisan(cli)
.虽然入口有两种但它们的启动过程却相差无几(具体可以再详细了解这两种方式).

基础启动

bootstrap/app.php
则是它的主要启动文件, 在
\Illuminate\Foundation\Application::__construct
中就可以看到应用主体的启动做了什么:

绑定Appliation和Container

注册最基础的Service Provider

注册别名

注册该应用程序的路径

上面启动过程的代码较简单,代码不分析了.就说一说为什么要做这几步,以及这几步对lavarel有什么作用.

laravel中以ioc为基础来构建应用程序的,所以,把这个最基础的Applicatoin放入容器中,供需要时可以随时从容器中提取使用(container 与 Application的关系看看代码就清晰了).

一个应用的合理运行必然离不开一些最基本的功能点,就像人类一样,虽然最重要的是大脑,但同样也不能没有血管,心脏.所以在laravel中也同样存在一些不可或缺的service provider, 比如事件和路由器.
\Illuminate\Events\EventServiceProvider
则把构建观察者的类注入到了ioc中,同时,在laravel源代码中大量使用了观察者模式来处理问题,
\Illuminate\Routing\RoutingServiceProvider
则把路由相关的服务注入到了主体中,因为一个http请求最不可或缺的当然是路由;

注册别名,则是为了调用ioc中的类时更方便,还有一点要注意是的,可以为一个类注册多个别名,为什么呢,其实这多个别名是存在关系的,它们大多是父类与子类的关系,就像Appliation和Container;

注册应用的路径则把一样常用的,跟应用有关的路径放到ioc中方便取用.启动的第一步到这就结束了.

http应用请求的启动

紧接着,又注册了三个类到ioc中,分别是http处理核心类,cli处理核心类,和异常处理.在这里注册了两种不同请亲的处理类,所以两个请求入口所做的事情都差不多了.接下来以http请求为例来,继续看下去.
public/index.php:50
则初始化了
\App\Http\Kernel::__construct
,也就初始化了中间件.接着
public/index.php:52
则调用了
\Illuminate\Foundation\Http\Kernel::handle
来处理请求,进一步看下去,也就是
\Illuminate\Foundation\Http\Kernel::bootstrap
中通过
Application::bootstrapWith
完成http请求环境的初始化,具体则是:

标记Application为已经引导启动状态

依次启动
\Illuminate\Foundation\Http\Kernel::$bootstrappers
中的项目

1.
Illuminate\Foundation\Bootstrap\DetectEnvironment
:设置应用程序的环境

2.
Illuminate\Foundation\Bootstrap\LoadConfiguration
:载入应用程序的配置文件

3.
Illuminate\Foundation\Bootstrap\ConfigureLogging
:绑定日志处理类

4.
Illuminate\Foundation\Bootstrap\HandleExceptions
:异常处理

5.
Illuminate\Foundation\Bootstrap\RegisterFacades
:Facade模式的应用

6.
Illuminate\Foundation\Bootstrap\RegisterProviders
:注册
Service Provider


7.
Illuminate\Foundation\Bootstrap\BootProviders
:标记启动完成 , 执行
Srvice Provider
register
方法,完成注入

然后,在
vendor/laravel/framework/src/Illuminate/Foundation/Http/Kernel.php:129
就进入到了路由器,进而进入对应Controller进行处理,最后完成处理,请求结束.这一部分就不说了.

cli请求的启动

这一部分略,步骤与http类似

从它的请求生命周期可以看出以下几点

1:
Service Provider
在启动阶段就已经与注入了IOC

2:分为了两种,一种是由系统控制,而另一种则是可由用户控制.第一种是构成应用程序的基础,不能缺少;第二种则将控制权交给用户,由用户掌控应用的运行,比如加载第三方
composer
包,或自定义的
Service
等等.

此时,模块化已经初现雏形.在Controller中,可以调用或组合不同的
Service
, 来完成特定的逻辑,因为它已经在IOC中了;我们可以控制不同的
Service
或增或减,自定义这个应用程序的功能,成为新的系统.接下来,再看看
Service Provider
做了什么,使模块化在laravel中更完善.

注册Service Provider

在注册基础的
Service Provider
中,不难发现,完成注册过程的是
\Illuminate\Foundation\Application::register
,这个方法比较简单,一是执行了
ServierProceder::register
方法,通过这个接口将
Service
注册动IOC中;二是在系统已经启动的情况下,执行
ServierProceder::boot
方法,作用在这里讲的很清楚.

在注册用户自定义(config/app.php:124)时,
\Illuminate\Foundation\Application::registerConfiguredProviders
则完成了注册过程,其处理核心
\Illuminate\Foundation\ProviderRepository::load
主要做了以下几步

1:解析所有的
Service Provider
, 通过它的defer属性来决定是否延迟加载

2:将解析的结果,也就是一个
Service Provider
的数组,缓存为文件,下次直接载入解析后的缓存文件

3:只加载defer属性不为ture的
Service Provider
, 并注册

4:将延迟加载的放支容器中(APP::$deferredServices),在需要的时候再加载

从注册过程可以看出,我们可以定义
Service Provider
加载的时间,并不仅仅在启动这过程中加载,而是在需要的时候再加载.一种是通过
\Illuminate\Foundation\Application::make
;还有一种方式延迟加载则是在when方法中通过事件注册到某项事件上去,这一点则要好好看看
\Illuminate\Foundation\ProviderRepository
类了.

理清它的注册过程后,我们再仔细看看
Service Provider
的抽象类,它作为基类,提供了
Servicer Provider
能做的所有事情.了解它能更好的理解
Service Provider
.这个类并不复杂,唯一一个不是很清晰的只有
commands
方法:它将命令注册到了
\Illuminate\Console\Events\ArtisanStarting
事件中,为什么这样做? 在cli时,启动时,会有该事件的执行,从而通过
Service Provider
把命令注入到了IOC中,这样执行命令就行云流水了.

到这里,用
Service Provider
来实现模块化的功能得到了强化,既可以延迟加载,还可以注册命令.接下来,通过一些例子,看看它具体做了什么.

Service Provider的使用

Service Provider有很多,我们随便挑两个来看看

QueueServiceProvider

\Illuminate\Queue\QueueServiceProvider
并非系统控制级别,看源代码,可以发现,里面有很多注册方法,注册了很多有关队列的类到IOC中,同时也注册了很多命令.在
provides
方法中,它返回的就是一个所有在这个
Service Provider
出现的的各个类,它是做什么的?其实我们可以发现,这个
Service Provider
是延迟加载的,所以这个
Service
所提供的各种服务并不会出现在服务中,上面我们说过,在需要的时候再加载.这一功能就是由
provides
中的返回值来决定的,当调用IOC中,那些延迟加载服务中出现的那些类时,再加载这些延迟的服务,从而可以获得延迟服务所提供的服务.

EventServiceProvider

\Illuminate\Events\EventServiceProvider
是应用程序的核心,它又做了什么呢?

它也是向IOC中注册了事件处理的类,同时为这个类设置了队列解析的类.

HashServiceProvider

\Illuminate\Hashing\HashServiceProvider
也向IOC注册一hash处理的类,并且是延迟加载的.

小结

查看
Service Provicer
的使用后,我们可以发现,它们都做了同们的事,就是把相应的服务注入到ICO中,以供使用,从而构成完成的系统.所以,现在我们就可以明白
Service Provider
是lararel完成模块化设计的方法,只不过融入了一些laravel自己的特点.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: