????????基本概念????????
????????它的主要工作是使用「服务容器」实现服务容器绑定、事件监听器、中间件,甚至是路由的注册。除核心服务外,几乎所有的服务提供者都定义在配置文件?config/app.php?文件中的?providers?节点中。服务提供者的典型处理流程是,当接 Laravel 应用接收到 HTTP 请求时会去执行服务提供者的 register方法,将各个服务绑定到容器内;之后,到了实际处理请求阶段,依据使用情况按需加载所需服务,也就是用到才加载,这样能够很明显提升性能。
????????一个服务提供者必须至少有一个 register 方法。当一个请求进入应用,框架启动时,所有罗列在配置文件里的服务提供者的 register 方法就会被调用。这在应用请求生命周期入口创建应用实例
的时候就发上了,比如
?
????????register 和?boot 方法:不要在 register 方法里面使用任何服务。该方法只是用来将对象绑定到服务容器的地方。所有关于绑定类的解析、交互都要在 boot 方法(服务提供者的另一个方法)里进行。
????????一些通过 Composer 安装的第三方扩展包也会有服务提供者。这些第三方扩展包的安装说明里一般都会告诉你要在配置文件 config/app.php 的 providers 数组里注册其提供的服务提供者,只有注册了对应的服务提供者,才能使用扩展包提供的服务。
????????包提供者的概念:不是所有的第三方扩展包都需要服务提供者。其实任何扩展包都不需要服务提供者,因为服务提供者只是启动服务组件并让它们可以直接使用,它们只是一个用来组织启动代码和容器绑定的地方 位置在config/app.php中,providers配置。
????????不是每一个罗列在配置文件 config/app.php 的 providers 数组里的服务提供者在每次请求时都需要被实例化。这会对性能有影响,尤其是服务提供者注册的服务在这个请求中根本用不到的情况下。例如,QueueServiceProvider 注册的服务就不是每次请求都用得到,只有在请求用到队列时才会用到。
????????需要注意的是在绑定接口实现类时使用 bind 还是 singleton 方法可以这样来考虑:如果在一次请求生命周期中该类只需要有一个实例,就使用 singleton;否则就使用 bind,也就是之前问过志颖的那个问题。
????????容器章节里面已经提到过,继承自 Illuminate\Support\ServiceProvider 的服务提供者都有一个 $app 属性,该属性是一个继承自 Container 类的完整 Illuminate\Foundation\Application 实例。因此,我们可以通过这个 $app 属性调用服务容器中的所有方法 ????????在所有服务提供者都注册以后(register 方法调用完),它们就进入了启动状态。这里将会触发每个服务提供者执行各自的 boot 方法。在使用服务提供者时,一种常见的错误就是在register 方法里面调用其他提供者注册的服务。由于在某个服务提供者的 register 方法里,不能保证所有其他服务都已经被注册,在该方法里调用别的服务有可能会出现该服务不可用。因此,调用其它服务的代码应该被定义在服务提供者的 boot 方法中。register 方法只能用于注册服务到容器。
在 boot 方法中,注册事件监听器、引入路由文件、注册过滤器、或者任何其他你能想到的事。但要先注册,在调用
框架核心
在 config/app.php 配置文件里面已经有了很多服务提供者,其中每一个都负责引导框架核心的一部分服务。比如MigrationServiceProvider 负责引导用于运行数据库迁移的类,包括Artisan 迁移命令。EventServiceProvide 负责引导和注册事件调度类。不同的服务提供者有着不同的复杂度,它们都负责引导核心的一部分功能。
有一点需要注意,大部分核心服务提供者是延迟加载的,意思是不是每次请求都会加载它们;不过,一些用于引导框架基础服务的服务提供者是每一次请求都会被加载的,比如 FilesystemServiceProvide 和 ExceptionServiceProvider。
|