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

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);
// (申请登记服务提供商)
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函数
 // 调用给定的闭包/类@方法并注入它的依赖项。
public function call($callback, array $parameters = [], $defaultMethod = null)
{
    return BoundMethod::call($this, $callback, $parameters, $defaultMethod);
}
	// (调用给定的闭包/类@方法并注入它的依赖项。)
    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是字符串,一般调不到。

// 确定给定的字符串是Class@method的语法
protected static function isCallableWithAtSign($callback)
{
    return is_string($callback) && strpos($callback, '@') !== false;
}

	// 使用Class@method语法调用对类的字符串引用
    protected static function callClass($container, $target, array $parameters = [], $defaultMethod = null)
    { 
        $segments = explode('@', $target);

	//我们将假定@符号用于从方法中分隔类名,方法名
	//我们将在这个@符号上进行分割,然后构建一个可调用数组,其中
	//我们可以直接传回依赖项绑定的“call”方法
        $method = count($segments) == 2
                        ? $segments[1] : $defaultMethod;

        if (is_null($method)) {
            throw new InvalidArgumentException('Method not provided.');
        }

        return static::call(
            $container, [$container->make($segments[0]), $method], $parameters
        );
    }

 // (调用已绑定到容器的方法。)

protected static function callBoundMethod($container, $callback, $default)
{
    if (! is_array($callback)) {
        return $default instanceof Closure ? $default() : $default;
    }
 
    // 这里,我们需要将数组可调用转换为可用于检查容器的Class@method字符串,
    //并查看是否存在这个给定方法的任何方法绑定。如果有,我们可以立即调用此方法绑定回调。
    $method = static::normalizeMethod($callback);
 
    if ($container->hasMethodBinding($method)) {
        return $container->callMethodBinding($method, $callback[0]);
    }
 
    return $default instanceof Closure ? $default() : $default;
}

	// 将给定的回调规范化为Class@method字符串
    protected static function normalizeMethod($callback)
    {
        $class = is_string($callback[0]) ? $callback[0] : get_class($callback[0]);

        return "{$class}@{$callback[1]}";
    }

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

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

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

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

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

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

return static::callBoundMethod($container, $callback, function () use ($container, $callback, $parameters) {
            return call_user_func_array(
                $callback, static::getMethodDependencies($container, $callback, $parameters)
            );
        });
        
        
// (获取给定方法的所有依赖项。)
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);
}

	// 获取给定回调的正确反射实例
    protected static function getCallReflector($callback)
    {
        if (is_string($callback) && strpos($callback, '::') !== false) {
            $callback = explode('::', $callback);
        }

        return is_array($callback)
                        ? new ReflectionMethod($callback[0], $callback[1])
                        : new ReflectionFunction($callback);
    }


	// 获取给定调用参数的依赖项
    protected static function addDependencyForCallParameter($container, $parameter,
                                                            array &$parameters, &$dependencies)
    {
        if (array_key_exists($parameter->name, $parameters)) {
            $dependencies[] = $parameters[$parameter->name];

            unset($parameters[$parameter->name]);
        } elseif ($parameter->getClass()) {
            $dependencies[] = $container->make($parameter->getClass()->name);
        } elseif ($parameter->isDefaultValueAvailable()) {
            $dependencies[] = $parameter->getDefaultValue();
        }
    }

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

return call_user_func_array(
                $callback, []
            );

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

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

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值