版权声明:本文为博主原创文章,未经博主允许不得转载。

register()是在服务容器注册服务,

bootstrap/app.php

/**
* 注册外部服务
*/
$app->register(Dingo\Api\Provider\LumenServiceProvider::class);
$app->register(Barryvdh\LaravelIdeHelper\IdeHelperServiceProvider::class);
$app->register(Maatwebsite\Excel\ExcelServiceProvider::class); /**
* 注册内部服务
*/
$app->register(App\Providers\User\UserServiceProvider::class);
$app->register(App\Providers\Validate\ValidateServiceProvider::class);
$app->register(App\Providers\Cache\CacheServiceProvider::class);
    /**
* Register a service provider with the application.(申请登记服务提供商)
*
* @param \Illuminate\Support\ServiceProvider|string $provider
* @return \Illuminate\Support\ServiceProvider
*/
public function register($provider)
{
    
if (! $provider instanceof ServiceProvider) {  
$provider = new $provider($this);
} if (array_key_exists($providerName = get_class($provider), $this->loadedProviders)) {
return;
} $this->loadedProviders[$providerName] = true; if (method_exists($provider, 'register')) {
$provider->register();
} if (method_exists($provider, 'boot')) {
return $this->call([$provider, 'boot']);
}
}
如果不是继承ServiceProvider,则直接new一个实例,传过去的$this是$app,那边类初始化时可以接收这个对象,然后操作容器;
如果该服务已注册,则直接返回;
标记为true;
如果有register函数则执行:
如果有boot函数,则调用call函数
    /**
* Call the given Closure / class@method and inject its dependencies.(调用给定的闭包/类@方法并注入它的依赖项。)
*
* @param callable|string $callback
* @param array $parameters
* @param string|null $defaultMethod
* @return mixed
*/
public function call($callback, array $parameters = [], $defaultMethod = null)
{
return BoundMethod::call($this, $callback, $parameters, $defaultMethod);
}
/**
* Call the given Closure / class@method and inject its dependencies.(调用给定的闭包/类@方法并注入它的依赖项。)
*
* @param \Illuminate\Container\Container $container
* @param callable|string $callback
* @param array $parameters
* @param string|null $defaultMethod
* @return mixed
*/
public static function call($container, $callback, array $parameters = [], $defaultMethod = null)
{
if (static::isCallableWithAtSign($callback) || $defaultMethod) {
return static::callClass($container, $callback, $parameters, $defaultMethod);
} return static::callBoundMethod($container, $callback, function () use ($container, $callback, $parameters) {
return call_user_func_array(
$callback, static::getMethodDependencies($container, $callback, $parameters)
);
});
}

第一个判断需要$callback是字符串,一般调不到。

    /**
* Determine if the given string is in Class@method syntax.(确定给定的字符串是类”方法的语法。)
*
* @param mixed $callback
* @return bool
*/
protected static function isCallableWithAtSign($callback)
{
return is_string($callback) && strpos($callback, '@') !== false;
}

接下来看callBoundMethod方法

    /**
* Call a method that has been bound to the container.(调用已绑定到容器的方法。)
*
* @param \Illuminate\Container\Container $container
* @param callable $callback
* @param mixed $default
* @return mixed
*/
protected static function callBoundMethod($container, $callback, $default)
{
if (! is_array($callback)) {
return $default instanceof Closure ? $default() : $default;
} // Here we need to turn the array callable into a Class@method string we can use to
// examine the container and see if there are any method bindings for this given
// method. If there are, we can call this method binding callback immediately.
$method = static::normalizeMethod($callback); if ($container->hasMethodBinding($method)) {
return $container->callMethodBinding($method, $callback[0]);
} return $default instanceof Closure ? $default() : $default;
}

判断是否为数组,不是的话,判断是否闭包,直接执行传过来的闭包或类;

将数组递归化为一个类@方法字符串;

检查容器,并查看该方法是否有任何方法绑定;

如果有的话,我们可以调用这个方法立即绑定回调;(好像用来验证的$this->methodBindings一直是空。。。)

如果没有,判断是否闭包,直接执行传过来的闭包或类;

我们再来看下调用callBoundMethod时传的闭包吧

return static::callBoundMethod($container, $callback, function () use ($container, $callback, $parameters) {
return call_user_func_array(
$callback, static::getMethodDependencies($container, $callback, $parameters)
);
});

先看下getMethodDependencies方法,

    /**
* Get all dependencies for a given method.(获取给定方法的所有依赖项。)
*
* @param \Illuminate\Container\Container
* @param callable|string $callback
* @param array $parameters
* @return array
*/
protected static function getMethodDependencies($container, $callback, array $parameters = [])
{
$dependencies = []; foreach (static::getCallReflector($callback)->getParameters() as $parameter) {
static::addDependencyForCallParameter($container, $parameter, $parameters, $dependencies);
} return array_merge($dependencies, $parameters);
}

基本都是返回空数组,暂时先不入这个坑了,应该是对给定的回调做反射处理,获取给定调用参数的依赖性。

return call_user_func_array(
$callback, []
);

那么多数情况,闭包函数执行的就是上面这段,而

$callback = [$provider, 'boot'];

所以说,就是执行了对应服务的boot方法,后面遇到其他情况,会继续做完善。

Lumen技术交流群:310493206

版权声明:本文为博主原创文章,未经博主允许不得转载。

Lumen开发:lumen源码解读之初始化(5)——注册(register)与启动(boot)的更多相关文章

  1. Lumen开发:lumen源码解读之初始化(4)——服务提供(ServiceProviders)与路由(Routes)

    版权声明:本文为博主原创文章,未经博主允许不得转载. 前面讲了singleton和Middleware,现在来继续讲ServiceProviders和Routes,还是看起始文件bootstrap/a ...

  2. Lumen开发:lumen源码解读之初始化(3)——单例(singleton)与中间件(Middleware)

    版权声明:本文为博主原创文章,未经博主允许不得转载. 今天来讲讲Lumen的singleton和Middleware,先来看看起始文件bootstrap/app.php / * | --------- ...

  3. mybatis源码解读(一)——初始化环境

    本系列博客将对mybatis的源码进行解读,关于mybatis的使用教程,可以查看我前面写的博客——传送门. 为了便于后面的讲解,我们这里首先构造一个统一环境.也可以参考mybatis官网. 1.数据 ...

  4. Lumen开发:lumen源码解读之初始化(2)——门面(Facades)与数据库(db)

    版权声明:本文为博主原创文章,未经博主允许不得转载. 紧接上一篇 $app->withFacades();//为应用程序注册门面. $app->withEloquent();//为应用程序 ...

  5. Lumen开发:lumen源码解读之初始化(1)——app实例

    版权声明:本文为博主原创文章,未经博主允许不得转载. 有些注释来着原文的百度翻译,可以有些难理解或者奇怪,我后面会根据自己的理解做调整的哈!!!不喜勿喷,层主英语不过关... 先来看看入口文件publ ...

  6. Spring-IOC源码解读2.3-BeanDefinition的注册

    在DefaultListAbleBeanFactory中通过一个HashMap持有载入的BeanDefinition信息 ,这个HashMap的定义在DefaultListAbleBeanFactor ...

  7. spring beans源码解读之--BeanFactory的注册

    beanFactory的继承关系如下图所示: (图片来源:http://www.myexception.cn/software-architecture-design/925888.html) 在上节 ...

  8. Vue 源码解读(2)—— Vue 初始化过程

    当学习成为了习惯,知识也就变成了常识. 感谢各位的 点赞.收藏和评论. 新视频和文章会第一时间在微信公众号发送,欢迎关注:李永宁lyn 文章已收录到 github 仓库 liyongning/blog ...

  9. SDWebImage源码解读之SDWebImageDownloaderOperation

    第七篇 前言 本篇文章主要讲解下载操作的相关知识,SDWebImageDownloaderOperation的主要任务是把一张图片从服务器下载到内存中.下载数据并不难,如何对下载这一系列的任务进行设计 ...

随机推荐

  1. 基于物品过滤的Slope One 算法

    Slope One 算法是由 Daniel Lemire 教授在 2005 年提出的一个 Item-Based 推荐算法. 他的主要优点是简单,易于扩展.实际上有多个Slope One算法,在此主要学 ...

  2. vue axios跨域请求,apache服务器设置

    问题所在axios请求会发送两次请求 也就是说,它会先使用options去测试,你这个接口是否能够正常通讯,如果不能就不会发送真正的请求过来,如果测试通讯正常,则开始正常请求. 思路: 跨域--> ...

  3. python定时执行方法

    1  time.sleep import time for i in range(5): print(i) time.sleep(10) 2 用shed import time import sche ...

  4. JS中的柯里化及精巧的自动柯里化实现

    一.什么是柯里化? 在计算机科学中,柯里化(Currying)是把接受多个参数的函数变换成接受一个单一参数(最初函数的第一个参数)的函数,并且返回接受余下的参数且返回结果的新函数的技术.这个技术由 C ...

  5. Oracle Study之-AIX6.1构建Oracle 10gR2 RAC(4)

    Oracle Study之-AIX6.1构建Oracle 10gR2 RAC(4) 一.安装CRS补丁 在安装CRS之前,须要安装补丁p6718715_10203_AIX64-5L,否则在安装时会出现 ...

  6. 移动web之响应式布局

    1.响应式布局的概念 响应式布局是Ethan Marcotte在2010年5月份提出的一个概念.简而言之.就是一个站点可以兼容多个终端--而不是为每一个终端做一个特定的版本号. 这个概念是为解决移动互 ...

  7. TFS 设置(转)

    一 参考以下两个链接进行相关软件的安装和用户权限配置: http://www.cnblogs.com/WilsonWu/archive/2011/11/24/2261674.html http://w ...

  8. C++Singleton的DCLP(双重锁)实现以及性能测评

      本文系原创,转载请注明:http://www.cnblogs.com/inevermore/p/4014577.html   根据维基百科,对单例模式的描述是: 确保一个类只有一个实例,并提供对该 ...

  9. ios网络学习------10 原生API文件上传

    使用原生态的api上传文件的实现: #import "MainViewController.h" @interface MainViewController () @propert ...

  10. 数据访问公共类(BaseProvider)

    using System; using System.Data; using System.Data.Common; using System.Configuration; using System. ...