Lumen开发:lumen源码解读之初始化(5)——注册(register)与启动(boot)

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

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

bootstrap/app.php

1
2
3
4
5
6
7
8
9
10
11
12
13
/**
   *  注册外部服务
   */
$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);

 

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
/**
 * Register a service provider with the application.(申请登记服务提供商)
 *
 * @param  \Illuminate\Support\ServiceProvider|string  $provider
 * @return \Illuminate\Support\ServiceProvider
 */
public function register($provider)
{<br>    
    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']);
    }
}
1
如果不是继承ServiceProvider,则直接new一个实例,传过去的$this$app,那边类初始化时可以接收这个对象,然后操作容器;<br>如果该服务已注册,则直接返回;<br>标记为true;<br>如果有register函数则执行:<br>如果有boot函数,则调用call函数<br><br>
1
2
3
4
5
6
7
8
9
10
11
12
/**
 * 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);
}

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/**
     * 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是字符串,一般调不到。

1
2
3
4
5
6
7
8
9
10
/**
 * 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方法

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
/**
 * 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时传的闭包吧

1
2
3
4
5
return static::callBoundMethod($container, $callback, function () use ($container, $callback, $parameters) {
            return call_user_func_array(
                $callback, static::getMethodDependencies($container, $callback, $parameters)
            );
        });

先看下getMethodDependencies方法,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
/**
 * 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);
}

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

1
2
3
return call_user_func_array(
                $callback, []
            );

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

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

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

Lumen技术交流群:310493206

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

posted @   程序生(Codey)  阅读(599)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 通过 API 将Deepseek响应流式内容输出到前端
· 因为Apifox不支持离线,我果断选择了Apipost!
点击右上角即可分享
微信分享提示