聊聊laravel中的Service Container

2022-05-15 0 240

什么是Service Container

The Laravel service container is a powerful tool for managing class dependencies and performing dependency injection.

从Laravel官方文档对于Service Container的解释可以看出,它的作用就是帮助我们管理和进行依赖注入的。

为什么要用Service Container

在《依赖注入》中,我们看到使用依赖注入可以极大的降低代码的耦合度,但是也带来了一个缺点,就是需要自己管理注入的对象。
如果一个组件有很多依赖,我们需要创建多个参数的setter方法来传递依赖关系,或者建立一个多个参数的构造函数来传递它们,另外在使用组件前还要每次都创建依赖,这让我们的代码像这样不易维护。
所以为依赖实例提供一个容器(Service Container),就是一个实用而且优雅的方法。
比如下面是laravel的入口文件(已去掉注释):

// public/index.php<?phprequire __DIR__.'/../bootstrap/autoload.php';$app = require_once __DIR__.'/../bootstrap/app.php';$kernel = $app->make(Illuminate\\Contracts\\Http\\Kernel::class);$response = $kernel->handle(    $request = Illuminate\\Http\\Request::capture());$response->send();$kernel->terminate($request, $response);
// bootstrap/app.php<?php$app = new Illuminate\\Foundation\\Application(    realpath(__DIR__.'/../'));$app->singleton(    Illuminate\\Contracts\\Http\\Kernel::class,    App\\Http\\Kernel::class);$app->singleton(    Illuminate\\Contracts\\Console\\Kernel::class,    App\\Console\\Kernel::class);$app->singleton(    Illuminate\\Contracts\\Debug\\ExceptionHandler::class,    App\\Exceptions\\Handler::class);return $app;

首先看bootstrap/app.php,其中$appIlluminate\\Foundation\\Application的一个实例,而Illuminate\\Foundation\\Application类继承自Container,所以$app实际上就是一个Service Container。
然后下面的三个singleton方法定义了当依赖Illuminate\\Contracts\\Http\\KernelIlluminate\\Contracts\\Console\\KernelIlluminate\\Contracts\\Debug\\ExceptionHandler这三个接口时,注入哪个类的单例。
然后看public/index.php,其中的make方法实际上就是用Service Container来new一个Illuminate\\Contracts\\Http\\Kernel实例,跟普通new的区别就是会把他的依赖自动注入进去。

是不是很简洁?

其实不单是Laravel,像Yii2、Phalcon等框架都通过实现容器来管理依赖注入。

如何使用Service Container

既然是一个容器,无非就是两个事,往里放东西和往外取东西,对应到Service Container就是绑定(Binding)和解析(Resolving)。

获得容器

在Laravel的Service Provider中,可以通过$this->app获取容器,除此之外,还可以使用app()来获取容器。
如果在Laravel外使用Service Container,直接new一个Illuminate\\Container\\Container就可以获得容器了。

以下都用$container代表获取到的容器。

绑定

绑定返回接口的实例

//使用闭包$container->bind('BarInterface', function(){    return new Bar();});//或者使用字符串$container->bind('FooInterface', 'Foo');

绑定单例

singletion 方法绑定一个只会被解析一次的类或接口至容器中,且后面的调用都会从容器中返回相同的实例:

$container->singleton('BarInterface', function(){    return new Bar();});

绑定实例

你也可以使用 instance 方法,绑定一个已经存在的对象实例至容器中。后面的调用都会从容器中返回指定的实例:

$bar = new Bar();$bar->setSomething(new Something);$container->instance('Bar', $bar);

情境绑定

有时候,你可能有两个类使用到相同接口,但你希望每个类都能注入不同实现。

$container->when('Man')          ->needs('PartnerInterface')          ->give('Woman');$container->when('Woman')          ->needs('PartnerInterface')          ->give('Man');

标记

有些时候,可能需要解析某个「分类」下的所有绑定。

$container->bind('Father', function () {    //});$container->bind('Mother', function () {    //});$container->bind('Daughter', function () {    //});$container->bind('Son', function () {    //});$container->tag(['Father', 'Mother', 'Daughter', 'Son'], 'familyMembers');$container->bind('Family', function ($container) {    return new Family($container->tagged('familyMembers'));});

解析

make方法

$foo = $container->make('Foo');

数组方法

$bar = $container['Bar'];

解析被标记绑定

$familyMembers = $container->tagged('familyMembers');foreach ($familyMembers as $inpidual) {    $inpidual->doSomething();}

解析事件

每当服务容器解析一个对象时就会触发事件。你可以使用 resolving 方法监听这个事件。

$container->resolving(function ($object, $container) {    // 当容器解析任何类型的对象时会被调用...});$container->resolving('Foo', function (Foo $foo, $container) {    // 当容器解析「Foo」类型的对象时会被调用...});

相关推荐:最新的五个Laravel视频教程

收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

【声明:根据2013年1月30日《计算机软件保护条例》2次修订第17条规定: 为了学习和研究软件内含的设计思想和原理,通过安装、显示、传输或者存 储软件等方式使用软件的,可以不经软件著作权人许可,不向其支付报酬! 鉴于此,也希望大家按此说明研究软件!】
本站所有源码尽量保证原汁原味,如有特殊情况会作出声明及标注,网站资源不做任何二次加密(原版加密除外,不影响程序使用的不会做解密处理),方便您更好的学习参考。 在您的能力范围内,为了大环境的良性发展,请尽可能的选择正版资源。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。

即刻码站__国内靠谱的站长资源下载平台 php教程 聊聊laravel中的Service Container https://www.jike1995.com/36088.html

常见问题
  • 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用
查看详情
  • 最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度
查看详情

相关文章

发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务