控制反转(IoC)和依赖注入(DI)
IoC 容器 —— Laravel 的核心
(1)laravel 的请求生命周期
几乎所有php框架,或者对php程序来说,都是单一入口,都是以index.php开始的。那么laravel的
入口文件都干了些什么事呢?
所有请求通过web服务器(apapache/nignx)引导至 public/index.php。
第一件事就是从bootstrap/app.php脚本中检索laravel应用程序的实例。
一 、引入app.php(创建一个新的应用)
$app = require_once __DIR__.'/../bootstrap/app.php';
app.php文件当中,第一件事就是创建一个新的实例;
$app = new Illuminate\Foundation\Application( realpath(__DIR__.'/../') );
(1) 实例化Application
class Application extends Container implements ApplicationContract, HttpKernelInterface
{
public function __construct($basePath = null)
{
if ($basePath) {
$this->setBasePath($basePath);
}
$this->registerBaseBindings();
$this->registerBaseServiceProviders();
$this->registerCoreContainerAliases();
}
}
实例化的时候干了4件事
- 绑定当前实例路径
- 注册基本绑定
- 注册所有基本服务提供者
- 注册所有核心依赖到容器中
(2)将重要的接口绑定到容器
$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
);
绑定单例到容器(http,kernel,debug)
(3)返回应用程序(当前实例)
二、启动应用程序
$kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);
这里 Illuminate\Contracts\Http\Kernel::class
只是一个接口,这里的$app->make()
这里有深入研究 Laravel 执行流程(五)之 认识 Make
简单来说就是从容器中解析给定的类型。那么这行代码可以理解为实例化位于app/Http/Kernel.php这个类。
(1)HTTP/控制器内核
所有请求都会Http的核心类(kernel)中的handle方法处理
这个handle方法长这个样子
public function handle($request)
{
try {
$request->enableHttpMethodParameterOverride();
$response = $this->sendRequestThroughRouter($request);
} catch (Exception $e) {
$this->reportException($e);
$response = $this->renderException($request, $e);
} catch (Throwable $e) {
$this->reportException($e = new FatalThrowableError($e));
$response = $this->renderException($request, $e);
}
$this->app['events']->dispatch(
new Events\RequestHandled($request, $response)
);
return $response;
}
简单来说就是创建了一个新的HTTP内核实例,并且实例化了一些重要的组件
应用程序的请求类型将传入的请求发送到 HTTP 内核或控制台内核。而这两个内核是用来作为所
有请求都要通过的中心位置。一个处理http请求,一个处理控制台请求。我们一般用到的是HTTP
内核。
$response = $kernel->handle( $request = Illuminate\Http\Request::capture() );
实例化了kernel传入了请求类
class Request extends SymfonyRequest implements Arrayable, ArrayAccess
{
}
继承了symfony的Request然后实现了一些接口。
从请求入口后面就可以开始处理自己业务逻辑了
三、返回
$response->send();
(2)服务容器与服务提供器
服务提供器
最重要的内核引导操作之一是加载应用程序的 服务提供器。应用程序的所有服务提供器都在 config/app.php 配置文件的 providers 数组中配置。首先,所有提供器都会调用 register 方法,接着,由 boot 方法负责调用所有被注册提供器。
服务提供器负责引导所有框架的各种组件,如数据库、队列、验证和路由组件。也就是说,框架提供的每个功能都它们来引导并配置。因此也可以说,服务提供器是整个 Laravel 引导过程中最重要的方面。
简单来说就是在容器中注册需要的类
服务容器
服务容器通过构造函数或者某些情况下通过 set 方法将类依赖注入到类中。说得专业点就是用于管理类依赖和执行依赖注入的强大工具
依赖注入与控制反转
我的理解:当一个类A需要实例化另一个类B,我们不在类A里面实例化,让其他类(专门的)来实例化,这个就叫控制反转。那怎么把实例化的类B放到类A,可以通过构造函数,或者set方法注入,这个就叫依赖注入。
在php当中一般使用类型提示注入依赖,比如管理员控制器需要注入,角色和权限
class AdminController extends controller
{
protected $user;
protected $role;
public function __construct(UserServices $userServices,RoleServices $roleServices)
{
$this->user=$userServices;
$this->role=$roleServices;
}
}
这里的
UserService
,RoleServices
为接口
在laravel中服务容器有一个强大的功能,就是将接口绑定到给定实现。如果需要用到服务容器,一般是注入接口,如果不是就接口,也就没有必要使用了。直接注入就行了,可以使用Repository模式,事实证明,服务容器很麻烦,如果不是超大型项目,根本没有必要使用。
Laravel 的核心就是一个 IoC 容器,高级的IOC容器,他会根据类的依赖需求,自动在注册、绑定的一堆实例中搜寻符合的依赖需求,并自动注入到构造函数参数中去。这种自动搜寻依赖需求的功能,是通过反射(Reflection)实现的。