资讯专栏INFORMATION COLUMN

[Laravel]唠唠Service Container

worldligang / 1146人阅读

摘要:比如下面是的入口文件已去掉注释首先看,其中是的一个实例,而类继承自,所以实际上就是一个。标记有些时候,可能需要解析某个分类下的所有绑定。解析方法数组方法解析被标记绑定解析事件每当服务容器解析一个对象时就会触发事件。

什么是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
make(IlluminateContractsHttpKernel::class);

$response = $kernel->handle(
    $request = IlluminateHttpRequest::capture()
);

$response->send();

$kernel->terminate($request, $response);
// bootstrap/app.php
singleton(
    IlluminateContractsHttpKernel::class,
    AppHttpKernel::class
);

$app->singleton(
    IlluminateContractsConsoleKernel::class,
    AppConsoleKernel::class
);

$app->singleton(
    IlluminateContractsDebugExceptionHandler::class,
    AppExceptionsHandler::class
);

return $app;

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

是不是很简洁?

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

如何使用Service Container

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

获得容器

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

以下都用$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 $individual) {
    $individual->doSomething();
}
解析事件

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

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

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

博客地址:http://haitian299.github.io/2016/05/17/laravel-service-container/

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/21566.html

相关文章

  • Laravel学习笔记之Container源码解析

    摘要:实际上的绑定主要有三种方式且只是一种的,这些已经在学习笔记之实例化源码解析聊过,其实现方法并不复杂。从以上源码发现的反射是个很好用的技术,这里给出个,看下能干些啥打印结果太长了,就不粘贴了。 说明:本文主要学习Laravel中Container的源码,主要学习Container的绑定和解析过程,和解析过程中的依赖解决。分享自己的研究心得,希望对别人有所帮助。实际上Container的绑...

    huayeluoliuhen 评论0 收藏0
  • Laravel学习笔记之IoC Container实例化源码解析

    摘要:说明本文主要学习容器的实例化过程,主要包括等四个过程。看下的源码如果是数组,抽取别名并且注册到中,上文已经讨论实际上就是的。 说明:本文主要学习Laravel容器的实例化过程,主要包括Register Base Bindings, Register Base Service Providers , Register Core Container Aliases and Set the ...

    ningwang 评论0 收藏0
  • Laravel Container (容器) 概念详解 (上)

    摘要:上文书,创建对象需要先创建对象。创建对象的杂活是嵌入在中的。对象使用来管理依赖关系非常好,但不是必须的。很容易实现,但手工维护各种乱七八糟的对象还是很麻烦。所有文章均已收录至项目。 本文翻译自 Symfony 作者 Fabien Potencier 的 《Dependency Injection in general and the implementation of a Depend...

    FullStackDeveloper 评论0 收藏0
  • 又一个强大的PHP5.3依赖注入容器

    摘要:现在我们就可以在构造函数或者任何其他通过服务容器注入依赖项的地方使用类型提示注入接口创建一个新的类实例,此处将注入的实例。自动解析构造函数所需的依赖的服务容器实现了接口。 简单的服务容器 一个简单的 php 5.3 依赖注入容器。 项目地址:https://github.com/godruoyi/easy-container Why 目前比较流行的 PHP 容器: Pimple La...

    sf190404 评论0 收藏0
  • Laravel修炼:服务容器绑定与解析

    摘要:用匿名函数的好处在于,这个服务绑定到容器以后,并不会立即产生服务最终的对象,只有在这个服务解析的时候,匿名函数才会执行,此时才会产生这个服务对应的服务实例。 前言   老实说,第一次老大让我看laravel框架手册的那天早上,我是很绝望的,因为真的没接触过,对我这种渣渣来说,laravel的入门门槛确实有点高了,但还是得硬着头皮看下去(虽然到现在我还有很多没看懂,也没用过)。  后面慢...

    The question 评论0 收藏0

发表评论

0条评论

worldligang

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<