核心概念 —— 服务容器
1、简介
Laravel 服务容器是一个用于管理类依赖和执行依赖注入的强大工具。依赖注入听上去很花哨,其实质是通过构造函数或者某些情况下通过 让我们看一个简单的例子:
在本例中, 深入理解 Laravel 服务容器对于构建功能强大的大型 Laravel 应用而言至关重要,对于贡献代码到 Laravel 核心也很有帮助。 几乎所有的服务容器绑定都是在服务提供者中完成。因此本章节的演示例子用到的容器都是在服务提供者中绑定。 注:如果一个类没有基于任何接口那么就没有必要将其绑定到容器。容器并不需要被告知如何构建对象,因为它会使用 PHP 的反射服务自动解析出具体的对象。 简单的绑定 在一个服务提供者中,可以通过 注意到我们将容器本身作为解析器的一个参数,然后我们可以使用该容器来解析我们正在构建的对象的子依赖。 绑定一个单例 绑定实例 你还可以使用 绑定原始值 你可能有一个接收注入类的类,同时需要注入一个原生的数值比如整型,可以结合上下文轻松注入这个类需要的任何值:
服务容器的一个非常强大的功能是其绑定接口到实现。我们假设有一个 这段代码告诉容器当一个类需要 有时侯我们可能有两个类使用同一个接口,但我们希望在每个类中注入不同实现,例如,两个控制器依赖 少数情况下,我们需要解析特定分类下的所有绑定,例如,你正在构建一个接收多个不同 这些服务被打上标签后,可以通过 有很多方式可以从容器中解析对象,首先,你可以使用 如果你所在的代码位置访问不了 最后,也是最常用的,你可以简单的通过在类的构造函数中对依赖进行类型提示来从容器中解析对象,控制器、事件监听器、队列任务、中间件等都是通过这种方式。在实践中,这是大多数对象从容器中解析的方式。 容器会自动为其解析类注入依赖,例如,你可以在控制器的构造函数中为应用定义的仓库进行类型提示,该仓库会自动解析并注入该类:
服务容器在每一次解析对象时都会触发一个事件,可以使用 正如你所看到的,被解析的对象将会传递给回调函数,从而允许你在对象被传递给消费者之前为其设置额外属性。set 方法将类依赖注入到类中。
<?php
namespace App\Http\Controllers;
use App\User;
use App\Repositories\UserRepository;
use App\Http\Controllers\Controller;
class UserController extends Controller
{
/**
* The user repository implementation.
*
* @var UserRepository
*/
protected $users;
/**
* Create a new controller instance.
*
* @param UserRepository $users
* @return void
*/
public function __construct(UserRepository $users)
{
$this->users = $users;
}
/**
* Show the profile for the given user.
*
* @param int $id
* @return Response
*/
public function show($id)
{
$user = $this->users->find($id);
return view('user.profile', ['user' => $user]);
}
}
UserController需要从数据源获取用户,所以,我们注入了一个可以获取用户的服务 UserRepository ,其扮演的角色类似使用 Eloquent 从数据库获取用户信息。注入 UserRepository 后,我们可以在其基础上封装其他实现,也可以模拟或者创建一个假的 UserRepository 实现用于测试。2、绑定
绑定基础
$this->app 变量访问容器,然后使用 bind 方法注册一个绑定,该方法需要两个参数,第一个参数是我们想要注册的类名或接口名称,第二个参数是返回类的实例的闭包:
$this->app->bind('HelpSpot\API', function ($app) {
return new HelpSpot\API($app->make('HttpClient'));
});
singleton 方法绑定一个只需要解析一次的类或接口到容器,然后接下来对容器的调用将会返回同一个实例:
$this->app->singleton('FooBar', function ($app) {
return new FooBar($app->make('HttpClient'));
});
instance 方法绑定一个已存在的对象实例到容器,随后 调用 容器将总是返回给定的实例:
$api = new HelpSpot\API(new HttpClient);
$this->app->instance('HelpSpot\Api', $api);
$this->app->when('App\Http\Controllers\UserController')
->needs('$variableName')
->give($value);
绑定接口到实现
EventPusher 接口及其实现类RedisEventPusher ,编写完该接口的 RedisEventPusher 实现后,就可以将其注册到服务容器:
$this->app->bind(
'App\Contracts\EventPusher',
'App\Services\RedisEventPusher'
);
EventPusher 的实现时将会注入 RedisEventPusher,现在我们可以在构造器或者任何其它通过服务容器注入依赖的地方进行 EventPusher 接口的依赖注入:
use App\Contracts\EventPusher;
/**
* 创建一个新的类实例
*
* @param EventPusher $pusher
* @return void
*/
public function __construct(EventPusher $pusher){
$this->pusher = $pusher;
}上下文绑定
Illuminate\Contracts\Filesystem\Filesystem 接口的不同实现。Laravel 为此定义了简单、平滑的接口:
use Illuminate\Support\Facades\Storage;
use App\Http\Controllers\VideoController;
use App\Http\Controllers\PhotoControllers;
use Illuminate\Contracts\Filesystem\Filesystem;
$this->app->when(PhotoController::class)
->needs(Filesystem::class)
->give(function () {
return Storage::disk('local');
});
$this->app->when(VideoController::class)
->needs(Filesystem::class)
->give(function () {
return Storage::disk('s3');
});
标签
Report 接口实现的报告聚合器,在注册完 Report 实现之后,可以通过 tag 方法给它们分配一个标签:
$this->app->bind('SpeedReport', function () {
//
});
$this->app->bind('MemoryReport', function () {
//
});
$this->app->tag(['SpeedReport', 'MemoryReport'], 'reports');tagged 方法来轻松解析它们:
$this->app->bind('ReportAggregator', function ($app) {
return new ReportAggregator($app->tagged('reports'));
});3、解析
make方法
make 方法,该方法接收你想要解析的类名或接口名作为参数:
$fooBar = $this->app->make('HelpSpot\API');
$app变量,可以使用辅助函数app:
$api = app('HelpSpot\API');
自动注入
<?php
namespace App\Http\Controllers;
use Illuminate\Routing\Controller;
use App\Users\Repository as UserRepository;
class UserController extends Controller{
/**
* 用户仓库实例
*/
protected $users;
/**
* 创建一个控制器实例
*
* @param UserRepository $users
* @return void
*/
public function __construct(UserRepository $users)
{
$this->users = $users;
}
/**
* 通过指定ID显示用户
*
* @param int $id
* @return Response
*/
public function show($id)
{
//
}
}4、容器事件
resolving 方法监听该事件:
$this->app->resolving(function ($object, $app) {
// Called when container resolves object of any type...
});
$this->app->resolving(HelpSpot\API::class, function ($api, $app) {
// Called when container resolves objects of type "HelpSpot\API"...
});
核心概念 —— 服务容器的更多相关文章
- Laravel开发:Laravel核心——Ioc服务容器源码解析(服务器绑定)
服务容器的绑定 bind 绑定 bind 绑定是服务容器最常用的绑定方式,在 上一篇文章中我们讨论过,bind 的绑定有三种: 绑定自身 绑定闭包 绑定接口 今天,我们这篇文章主要从源码上讲解 Ioc ...
- Laravel开发:Laravel核心——Ioc服务容器源码解析(服务器解析)
make解析 服务容器对对象的自动解析是服务容器的核心功能,make 函数.build 函数是实例化对象重要的核心,先大致看一下代码: public function make($abstract) ...
- Laravel开发:Laravel核心——Ioc服务容器
服务容器 在说 Ioc 容器之前,我们需要了解什么是 Ioc 容器. Laravel 服务容器是一个用于管理类依赖和执行依赖注入的强大工具. 在理解这句话之前,我们需要先了解一下服务容器的来龙去脉: ...
- Docker概念学习系列之Docker核心概念之容器container
不多说,直接上干货! Docker 利用容器来运行应用. 容器是从镜像创建的运行实例. 它可以被启动.开始.停止.删除.每个容器都是相互隔离的.保证安全的平台. 可以把容器看做是一个简易版的 Linu ...
- laravel服务容器(IOC控制反转,DI依赖注入),服务提供者,门脸模式
laravel的核心思想: 服务容器: 容器:就是装东西的,laravel就是一个个的对象 放入:叫绑定 拿出:解析 使用容器的目的:这里面讲到的是IOC控制反转,主要是靠第三方来处理具体依赖关系的解 ...
- docker核心概念(镜像、容器、仓库)及基本操作
概要 docker是一种linux容器技术.容器有效的将由单个操作系统挂管理的资源划分到孤立的组中,以便更好的在组之间平衡有冲突的资源使用需求.可简单理解为一种沙盒 .每个容器内运行一个应用,不同的容 ...
- 01 . 容器编排简介及Kubernetes核心概念
Kubernetes简介 Kubernetes是谷歌严格保密十几年的秘密武器-Borg的一个开源版本,是Docker分布式系统解决方案.2014年由Google公司启动. Kubernetes提供了面 ...
- 面向服务的体系结构(SOA)——(1)目标与核心概念
什么是SOA? 常常听到人们拿OOP和SOA一起来说事,诸如SOA是否可以代替面向对象(OOP)或者两者比哪个更加有优势?直接回答有难度举个例子可能显得答案更容易理解.小孩子问你该认真写作业呢?还是高 ...
- 转 Laravel 的核心 —— 服务容器
具体内容请参考 1.laravel 学习笔记 —— 神奇的服务容器 - 灵感 - 来自生活的馈赠https://www.insp.top/article/learn-laravel-container ...
随机推荐
- [C语言 - 7] 结构体struct
A. 基本知识 与数组的对比 数组: 构造类型 只能有多个相同类型的数据构成 结构体: 结构体类型 可以由多个不同类型的数据构成 1. 定义类型 struct Student { int ...
- ASP.NET MVC- 使用PageList.Mvc分页
ASP.NET MVC中进行分页的方式有多种,在NuGet上有提供使用PagedList.PagedList.Mvc进行分页. 1. 通过NuGet引用PagedList.Mvc 在安装引用Paged ...
- Volley使用指南第三回(来自developer.android)
继第二篇之后,再来Volley使用的教程的第三篇,有些翻译我是根据自己的理解,可能有错误的地方,还请多多包涵. 标准请求 这一回课将会告诉你Volley能够完成的3种请求类型 1.StringReqe ...
- CentOS 6系统下安装 JDK1.6
CentOS 6系统下安装 JDK1.6 JDK(Java Development Kit)是Sun Microsystems针对Java开发员的产品.自从Java推出以来,JDK已经成为使用最广泛的 ...
- MATLAB新手教程
MATLAB新手教程 .MATLAB的基本知识 1-1.基本运算与函数 在MATLAB下进行基本数学运算,仅仅需将运算式直接打入提示号(>>)之後,并按入Enter键就可以.比如 ...
- 实现控件WPF(4)----Grid控件实现六方格
PS:今天上午,非常郁闷,有很多简单基础的问题搞得我有些迷茫,哎,代码几天不写就忘.目前又不当COO,还是得用心记代码哦! 利用Grid控件能很轻松帮助我们实现各种布局.上面就是一个通过Grid单元格 ...
- Codeforces Round #334 (Div. 2) A. Uncowed Forces 水题
A. Uncowed Forces Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/604/pro ...
- BZOJ 1079: [SCOI2008]着色方案 记忆化搜索
1079: [SCOI2008]着色方案 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/p ...
- poj1190生日蛋糕
生日蛋糕 Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 12277 Accepted: 4325 Description 7月1 ...
- Nginx Rewrite 实现匹配泛域名规则
Nginx 是一个高性能的 HTTP 和 反向代理 服务器,也是一个 IMAP/POP3/SMTP 代理服务器. Nginx 是由 Igor Sysoev 为俄罗斯访问量第二的 Rambler.ru ...