关于使用 Laravel 服务容器的优势介绍

数智先锋旅人
• 阅读 104

如果说laravel框架的核心是什么,那么无疑是服务容器。理解服务容器的概念,对于我们使用laravel太重要了,应该说是否理解服务容器的概念是区分是否入门laravel的重要条件。因为整个框架正是在服务容器这一基础上构建起来的。

laravel服务容器就像一个高度自动化的工厂,你需要的东西,定制好模型,使用特定接口来制造。

因为使用了服务容器,laravel中大部分对象实例化的方式是这样的:

1
2
3
$obj1 = $container->make('class1', 'class2');

$obj2 = $container->make('class3', 'class4');

但是在没有使用服务容器的情况下,以下这种方式同样可以做到:

1
2
3
$obj1 = new class1(new class2());

$obj2 = new class3(new class4());

那么使用服务容器的优势到底是什么呢?下面我们通过一些具体例子来分析下它的优势:

例一、发送邮件

我们把发送邮件的功能封装成一个类,需要使用的时候,实例化并调用发送方法。

以下是不使用laravel服务容器常见的方式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**

*发送邮件服务类

*/

class EmailService{

public function send(){

//todo 发送邮件方法

}

}

//如果任何地方要发邮件我们就复制下面这两行代码

$emailService = new EmailService();

$emailService->send();

使用了了laravel服务容器以后:

1
2
3
4
5
6
7
8
9
10
11
$this->app->bind('emailService', function ($app) {

return new EmailService();

});

//如果任何地方要发邮件我们就复制下面这两行代码

$emailService = app('emailService');

$emailService->send();

这使得我们的代码更加简洁了,并且由于有了中间层,灵活性提高了(解耦),那么无论是测试(在测试时我们可以伪造类替换EmailService类)还是优化EmailService类,都变得更加方便。

1
2
3
4
5
6
7
//只需要改这一个地方

$this->app->bind('emailService', function ($app) {

return new SupperEmailService();

});

其他调用的部分我们完全不用动,如果我们没有这个绑定操作,那么不得不在每个使用邮件服务的地方做更改。

1
2
3
4
5
//使用到EamilSerice类的每个地方都要更改

$emailService = new SupperEmailService();

$emailService->send();

例二、实现单例模式

还是上面的例子,出于性能的考虑,你需要SupperEamilService类实现单例模式,于是在不使用laravel服务容器的情况下,你将SupperEmailService类更改如下:

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
class SupperEamilService{

//创建静态私有的变量保存该类对象

static private $instance;

//防止直接创建对象

private function __construct(){

}

//防止克隆对象

private function __clone(){

}

static public function getInstance(){

//判断$instance是否是Uni的对象

//没有则创建

if (!self::$instance instanceof self) {

self::$instance = new self();

}

return self::$instance;

}

//发送邮件方法

public function send(){

}

}

除此之外,由于现在SupperEamilService类构造函数为私有,无法通过new关键字来实例化对象,所以在每个实例化SupperEmailService类的地方都要改成这样:

1
2
3
$emailService=SupperEmailService::getInstance();

$emailService->send();

laravel服务容器天生支持单例,下面是laravel的实现方式:

1
2
3
4
5
6
7
//只需要把bind改成singleton

$this->app->singleton('emailService', function ($app) {

return new SupperEmailService();

});

要实现单例甚至只需要改一行代码,把原来的bind方法改成singleton ,通过容器取出来的便是单例,真是太方便了。

例三、旅行者去旅行

这个例子假设一个旅行者去西藏旅行,可以做火车(train)或者走路(leg)去。

不使用laravel服务容器:

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
<?php

interface TrafficTool

{

public function go();

}

class Train implements TrafficTool

{

public function go()

{

echo "train....";

}

}

class Leg implements TrafficTool

{

public function go()

{

echo "leg..";

}

}

class Traveller

{

/**

* @var Leg|null|Train

* 旅行工具

*/

protected $_trafficTool;

public function __construct(TrafficTool $trafficTool)

{

$this->\_trafficTool = $trafficTool;

}

public function visitTibet()

{

$this->_trafficTool->go();

}

}

当旅行者要坐火车去旅行通常我们这样写:

1
2
3
4
5
6
7
<?php

$train = new Train();

$tra = new Traveller($train);

$tra->visitTibet();

事实上这种写法已经非常不错了,因为对于旅行工具的依赖已经通过接口的方式转移到外部了。但是使用new来实例化对象的时候还是会产生依赖.比如上面trafficTool),这说明我们要创建一个Traveller之前必须得有一个$trafficTool,即Traveller依赖于trafficTool.当使用new来实例化Traveller的时候,Traveller和trafficTool之间就产生了耦合.这样,这两个组件就没办法分开了。

现在我们来看看使用laravel服务容器是怎么实现的:

在服务容器中绑定类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?php

namespace App\Providers;

use Laravel\Lumen\Providers\EventServiceProvider as ServiceProvider;

class RepositoryServiceProvider extends ServiceProvider

{

public function register()

{

//在服务容器中绑定类

$this->app->bind( 'TrafficTool', 'Train');

$this->app->bind('Traveller', 'Traveller');

}

}

实例化对象
1
2
3
4
5
6
7
<?php

// 实例化对象

$tra = app()->make('Traveller');

$tra->visitTibet();

当我们使用服务容器获取旅行类的对象时,容器会自动注入对象所需要的参数。而在此之前我只需要绑定特定的类就可以了,这样做才体现了真正的自动化,而且使得旅行类和旅行工具类完全解耦了。当我们需要更改旅行方式的时候,我们就只需要更改绑定就可以了。

点赞
收藏
评论区
推荐文章
手把手带你开发starter,点对点带你讲解原理
在2012年10月,一个叫MikeYoungstrom的人在SpringJira中创建了一个功能请求,要求在SpringFramework中支持无容器Web应用程序体系结构,提出了在主容器引导Spring容器内配置Web容器服务;这件事情对SpringBoot的诞生应该说是起到了一定的推动作用。
Easter79 Easter79
4年前
spring容器发布dubbo服务
spring容器发布dubbo服务spring发布dubbo服务,只需要启动spring框架即可,不需要利用tomcat等容器,节省资源publicclassMain{publicstaticvoidmain(Stringargs){com.alibaba.du
Stella981 Stella981
4年前
Linux安装Composer
Composer是php的一个包管理器,使用Composer能极大的提高我们的代码效率。当我们需要使用优雅的laraverl框架时我们一定不能绕过Composer当然Composer不是只为laravel服务的,他是为整个php服务的。(Composer需要php5.3.2以上才能运行)1.下载Composer包curl
Stella981 Stella981
4年前
Laravel使用redis保存SESSION
Laravel使用redis保存SESSION首先确认服务器已经安装redis服务,php安装了redis扩展.1.打开config/database.php。在redis配置项中增加session的连接'session''host'
Stella981 Stella981
4年前
Laravel的生命周期
Laravel的生命周期世间万物皆有生命周期,当我们使用任何工具时都需要理解它的工作原理,那么用起来就会得心应手,应用开发也是如此。理解了它的原理,那么使用起来就会游刃有余。在了解Laravel的生命周期前,我们先回顾一下PHP的生命周期。PHP的生命周期PHP的运行模
Stella981 Stella981
4年前
Laravel处理session(会话)的方法详解
在Web应用程序中,有必要识别跨越请求的用户并为每个用户保存数据,为此,像Laravel这样的框架提供了一种称为会话的机制。本篇文章就来为大家介绍关于Laravel处理session(会话)的方法。!laravel(https://oscimg.oschina.net/oscnet/f7951cdc35af1b61cc4dd6bd63973e2924
Stella981 Stella981
4年前
Registry 容器镜像服务端细节
引言通常我们在使用集群或者容器的时候,都会接触到存储在本地的镜像,也或多或少对本地镜像存储有一定的了解。但是服务端的镜像存储细节呢?本文主要介绍容器镜像的服务端存储结构,对于自建镜像服务或是对容器镜像底层原理或优化有兴趣的同学可以了解一下。相关开源项目目前容器镜像服务相关的开源项目主要有以下两个。R
Stella981 Stella981
4年前
Docker 容器介绍
Docker容器介绍_Docker_是一个基于_Go_语言的开源应用容器引擎,它既能实现虚拟化,又可用于将应用服务打包成轻量、可移植的容器,从而可以发布到任何_Linux_平台。除了优秀了沙箱机制外,_Docker_容器的开销也极低。正如其名,_Docker_所做的事情正是以一个集装箱的身份承载应用服务的运行
cAdvisor监控Docker容器做性能测试
cAdvisor监控Docker容器做性能测试缘起当前有个服务做技术选型,服务要求比较高的性能,要做性能测试。部署的环境是容器话部署,但申请新的容器流程较长,于是我打算在流程走完之前简单评估下性能,来确定技术选型是否可行。当前有一个测试服务器上装有Dock
容器镜像服务:云原生时代的核心基石
随着云计算技术的快速发展,容器化技术已成为应用部署的主流方式。容器镜像服务作为容器技术的重要组成部分,为应用提供了可靠、高效、一致的运行环境。本文将对容器镜像服务的概念、原理、应用场景以及未来发展趋势进行深入探讨,旨在帮助读者更好地理解和应用容器镜像服务。
容器、容器云和容器化PaaS平台之间到底是什么关系?
容器是一种操作系统级虚拟化技术,Docker是一种容器引擎。使用Docker来运行操作容器。但从容器自身来说,其提供的是IaaS层能力。Kubernetes提供了容器调度和管理的能力,加上云计算租户功能,实现容器云平台功能。而基于容器技术所构建的应用开发、应用托管和应用运维平台则可以称为容器化PaaS平台,它是一种轻量化PaaS实现。结合日志、监控、认证、权限等基础能力则可以构建企业级的平台和可复用服务,采用微服务架构实现企业技术服务中台能力,支撑企业业务敏捷研发和模式转型。