成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專(zhuān)欄INFORMATION COLUMN

Laravel核心——Ioc服務(wù)容器源碼解析(服務(wù)器解析)

hearaway / 820人閱讀

摘要:而函數(shù)作用是加載延遲服務(wù),與容器解析關(guān)系不大,我們放在以后再說(shuō)。在構(gòu)造之前,服務(wù)容器會(huì)先把放入中,繼而再去解析。利用服務(wù)容器解析依賴(lài)的參數(shù)。

make解析

首先歡迎關(guān)注我的博客: www.leoyang90.cn

服務(wù)容器對(duì)對(duì)象的自動(dòng)解析是服務(wù)容器的核心功能,make 函數(shù)、build 函數(shù)是實(shí)例化對(duì)象重要的核心,先大致看一下代碼:

public function make($abstract)
{
    $abstract = $this->getAlias($abstract);

    if (isset($this->deferredServices[$abstract])) {
        $this->loadDeferredProvider($abstract);
    }

    return parent::make($abstract);
}
    public function make($abstract)
    {
        return $this->resolve($abstract);
    }
    
    public function resolve($abstract, $parameters = [])
    {
        $abstract = $this->getAlias($abstract);
        
        $needsContextualBuild = ! empty($parameters) || ! is_null(
            $this->getContextualConcrete($abstract)
        );

        // If an instance of the type is currently being managed as a singleton we"ll
        // just return an existing instance instead of instantiating new instances
        // so the developer can keep using the same objects instance every time.
        if (isset($this->instances[$abstract]) && ! $needsContextualBuild) {
            return $this->instances[$abstract];
        }

        $concrete = $this->getConcrete($abstract);

        // We"re ready to instantiate an instance of the concrete type registered for
        // the binding. This will instantiate the types, as well as resolve any of
        // its "nested" dependencies recursively until all have gotten resolved.
        if ($this->isBuildable($concrete, $abstract)) {
            $object = $this->build($concrete);
        } else {
            $object = $this->make($concrete);
        }

        // If we defined any extenders for this type, we"ll need to spin through them
        // and apply them to the object being built. This allows for the extension
        // of services, such as changing configuration or decorating the object.
        foreach ($this->getExtenders($abstract) as $extender) {
            $object = $extender($object, $this);
        }

        // If the requested type is registered as a singleton we"ll want to cache off
        // the instances in "memory" so we can return it later without creating an
        // entirely new instance of an object on each subsequent request for it.
        if ($this->isShared($abstract) && ! $needsContextualBuild) {
            $this->instances[$abstract] = $object;
        }

        $this->fireResolvingCallbacks($abstract, $object);

        $this->resolved[$abstract] = true;

        return $object;
    }

在講解解析流程之前,我們先說(shuō)說(shuō)使用make函數(shù)進(jìn)行解析的分類(lèi):

我們?cè)敿?xì)的講一下上圖。這里我把使用make函數(shù)進(jìn)行解析的情況分為大致兩種:

解析對(duì)象沒(méi)有綁定過(guò)任何類(lèi),例如:

$app->make("AppHttpControllersHomeController");

解析對(duì)象綁定過(guò)實(shí)現(xiàn)類(lèi)

對(duì)于綁定過(guò)實(shí)現(xiàn)類(lèi)的對(duì)象可以分為兩種:

綁定的是類(lèi)名,例如:

$app->when("AppHttpControllersHomeController")
->needs("AppHttpRequestsInRequest")
->give("AppHttpRequestsTestsRequest");

綁定的是閉包

對(duì)于綁定的是閉包的又可以分為:

用戶(hù)綁定閉包,例如:

$app->singleton("auth",function($app){
    return new AuthManager($app)
});//對(duì)象類(lèi)直接實(shí)現(xiàn)方法

$app->singleton(EloquentFactory::class, function ($app) {
    return EloquentFactory::construct(
        $app->make(FakerGenerator::class), database_path("factories")
);//對(duì)象類(lèi)依賴(lài)注入
});

服務(wù)容器外包一層閉包函數(shù)(make/build),例如:

$app->singleton(
    IlluminateContractsHttpKernel::class,
    AppHttpKernel::class
);//包裝make

$app->singleton(
    AppConSoleKernel::class,
);//包裝build

我們?cè)谶@里先大致講一下服務(wù)容器解析的流程,值得注意的是其中 build 函數(shù)有可能會(huì)遞歸調(diào)用 make:

獲取服務(wù)名稱(chēng)。

加載延遲服務(wù)。判斷當(dāng)前的接口是否是延遲服務(wù)提供者,若是延遲服務(wù)提供者,那么還要對(duì)服務(wù)提供者進(jìn)行注冊(cè)與啟動(dòng)操作。

解析單例。如果接口服務(wù)是已經(jīng)被解析過(guò)的單例對(duì)象,而且并非上下文綁定,那么直接取出對(duì)象。

獲取注冊(cè)的實(shí)現(xiàn)。實(shí)現(xiàn)方式可能是上下文綁定的,也可能是 binding 數(shù)組中的閉包,也有可能就是接口本身。

build 解析。首先判斷是否需要遞歸。是,則遞歸 make;否,則調(diào)用 build 函數(shù);直到調(diào)用 build 為止

執(zhí)行擴(kuò)展。若當(dāng)前解析對(duì)象存在擴(kuò)展,運(yùn)行擴(kuò)展函數(shù)。

創(chuàng)造單例對(duì)象。若 shared 為真,且不存在上下文綁定,則放入單例數(shù)組中

回調(diào)

標(biāo)志解析

下面我們開(kāi)始詳細(xì)分解代碼邏輯。由于 getAlias 函數(shù)已經(jīng)在 上一篇 講過(guò),這里不會(huì)再說(shuō)。而loadDeferredProvider 函數(shù)作用是加載延遲服務(wù),與容器解析關(guān)系不大,我們放在以后再說(shuō)。

獲取注冊(cè)的實(shí)現(xiàn)

獲取解析類(lèi)的真正實(shí)現(xiàn),函數(shù)優(yōu)先去獲取上下文綁定的實(shí)現(xiàn),否則獲取 binding 數(shù)組中的實(shí)現(xiàn),獲取不到就是直接返回自己作為實(shí)現(xiàn):

protected function getConcrete($abstract)
{
    if (! is_null($concrete = $this->getContextualConcrete($abstract))) {
        return $concrete;
    }

    if (isset($this->bindings[$abstract])) {
        return $this->bindings[$abstract]["concrete"];
    }

    return $abstract;
}

一般來(lái)說(shuō),上下文綁定的服務(wù)是通過(guò)依賴(lài)注入來(lái)實(shí)現(xiàn)的:

$this->app->when(PhotoController::class)
          ->needs(Filesystem::class)
          ->give(function () {
              return Storage::disk("local");
          });
       
class PhotoController{
    protected $file;

    public function __construct(Filesystem $file){
      $this->file = $file;
    }
}

服務(wù)容器會(huì)在解析 PhotoController 的時(shí)候,通過(guò)放射獲取參數(shù)類(lèi)型 Filesystem,并且會(huì)把 Filesystem 自動(dòng)解析為 Storage::disk("local")。如何實(shí)現(xiàn)的呢?首先,從 上一篇 文章我們知道,當(dāng)進(jìn)行上下文綁定的時(shí)候,實(shí)際上是維護(hù) contextual 數(shù)組,通過(guò)上下文綁定,這個(gè)數(shù)組中存在:

contextual[PhotoController][Filesystem] = function () { return Storage::disk("local"); }

若是服務(wù)容器試圖構(gòu)造 PhotoController 類(lèi),那么由于其構(gòu)造函數(shù)依賴(lài)于 Filesystem,所以容器必須先生成 Filesystem 類(lèi),然后再注入到 PhotoController 中。

在構(gòu)造 Filesystem 之前,服務(wù)容器會(huì)先把 PhotoController 放入 buildStack 中,繼而再去解析 Filesystem。

解析 Filesystem 時(shí),運(yùn)行 getContextualConcrete 函數(shù):

protected function getContextualConcrete($abstract)
{
    if (! is_null($binding = $this->findInContextualBindings($abstract))) {
        return $binding;
    }
     
    if (empty($this->abstractAliases[$abstract])) {
        return;
    }

    foreach ($this->abstractAliases[$abstract] as $alias) {
        if (! is_null($binding = $this->findInContextualBindings($alias))) {
            return $binding;
        }
    }
}
 
protected function findInContextualBindings($abstract)
{
    if (isset($this->contextual[end($this->buildStack)][$abstract])) {
        return $this->contextual[end($this->buildStack)][$abstract];
    }
}

從上面可以看出,getContextualConcrete 函數(shù)把當(dāng)前解析的類(lèi)(Filesystem)作為 abstract,buildStack 最后一個(gè)類(lèi)(PhotoController)作為 concrete,尋找 this->contextual[concrete] [abstract] (contextual[PhotoController] [Filesystem])中的值,在這個(gè)例子里面這個(gè)數(shù)組值就是那個(gè)匿名函數(shù)。

build 解析

對(duì)于服務(wù)容器來(lái)說(shuō),綁定是可以遞歸的,例如:

$app->bind("a","b");
$app->bind("b","c");
$app->bind("c",function(){
    return new C;
  })

遇到這樣的情況,bind 綁定中 getClosure 函數(shù)開(kāi)始發(fā)揮作用,該函數(shù)會(huì)給類(lèi)包一層閉包,閉包內(nèi)調(diào)用 make 函數(shù),服務(wù)容器會(huì)不斷遞歸調(diào)用 make 函數(shù),直到最后一層,也就是綁定 c 的匿名函數(shù)。但是另一方面,有一些綁定方式并沒(méi)有調(diào)用 bind 函數(shù),例如上下文綁定 context:

$this->app->when(E::class)
          ->needs(F::class)
          ->give(A::class);

當(dāng)make(E::class)的時(shí)候,getConcrete 返回 A 類(lèi),而不是調(diào)用 make 函數(shù)的閉包,所以并不會(huì)啟動(dòng)遞歸流程得到 C 的匿名函數(shù),所以造成 A 類(lèi)完全無(wú)法解析,isBuildable 函數(shù)就是解決這種問(wèn)題的,當(dāng)發(fā)現(xiàn)需要解析構(gòu)造的對(duì)象很有可能是遞歸的,那么就遞歸調(diào)用 make 函數(shù),否則才會(huì)調(diào)用build。

...
if ($this->isBuildable($concrete, $abstract)) {
        $object = $this->build($concrete);
    } else {
        $object = $this->make($concrete);
    }
...
     
protected function isBuildable($concrete, $abstract)
{
    return $concrete === $abstract || $concrete instanceof Closure;
}
執(zhí)行擴(kuò)展

獲取擴(kuò)展閉包,并運(yùn)行擴(kuò)展函數(shù):

protected function getExtenders($abstract)
{
    $abstract = $this->getAlias($abstract);

    if (isset($this->extenders[$abstract])) {
        return $this->extenders[$abstract];
    }

    return [];
}
回調(diào)

先后啟動(dòng)全局的解析事件回調(diào)函數(shù),再啟動(dòng)針對(duì)類(lèi)型的事件回調(diào)函數(shù):

protected function fireResolvingCallbacks($abstract, $object)
{
    $this->fireCallbackArray($object, $this->globalResolvingCallbacks);

    $this->fireCallbackArray(
        $object, $this->getCallbacksForType($abstract, $object, $this->resolvingCallbacks)
    );

    $this->fireAfterResolvingCallbacks($abstract, $object);
}

protected function getCallbacksForType($abstract, $object, array $callbacksPerType)
{
    $results = [];

    foreach ($callbacksPerType as $type => $callbacks) {
        if ($type === $abstract || $object instanceof $type) {
            $results = array_merge($results, $callbacks);
        }
    }

    return $results;
}
 
protected function fireAfterResolvingCallbacks($abstract, $object)
{
    $this->fireCallbackArray($object, $this->globalAfterResolvingCallbacks);

    $this->fireCallbackArray(
        $object, $this->getCallbacksForType($abstract, $object, $this->afterResolvingCallbacks)
    );
 
build 解析

make 函數(shù)承擔(dān)了解析的大致框架,build 主要的職責(zé)就是利用反射將類(lèi)構(gòu)造出來(lái),先看看主要代碼:

public function build($concrete)
{
    // If the concrete type is actually a Closure, we will just execute it and
    // hand back the results of the functions, which allows functions to be
    // used as resolvers for more fine-tuned resolution of these objects.
    if ($concrete instanceof Closure) {
         return $concrete($this, $this->getLastParameterOverride());
    }

    $reflector = new ReflectionClass($concrete);

    // If the type is not instantiable, the developer is attempting to resolve
    // an abstract type such as an Interface of Abstract Class and there is
    // no binding registered for the abstractions so we need to bail out.
    if (! $reflector->isInstantiable()) {
        return $this->notInstantiable($concrete);
    }

    $this->buildStack[] = $concrete;

    $constructor = $reflector->getConstructor();

    // If there are no constructors, that means there are no dependencies then
    // we can just resolve the instances of the objects right away, without
    // resolving any other types or dependencies out of these containers.
    if (is_null($constructor)) {
        array_pop($this->buildStack);

        return new $concrete;
    }

    $dependencies = $constructor->getParameters();

    // Once we have all the constructor"s parameters we can create each of the
    // dependency instances and then use the reflection instances to make a
    // new instance of this class, injecting the created dependencies in.
    $instances = $this->resolveDependencies(
        $dependencies
    );

    array_pop($this->buildStack);

    return $reflector->newInstanceArgs($instances);
}

我們下面詳細(xì)的說(shuō)一下各個(gè)部分:

閉包函數(shù)執(zhí)行
if ($concrete instanceof Closure) {
     return $concrete($this, $this->getLastParameterOverride());
}

這段代碼很簡(jiǎn)單,但是作用很大。前面說(shuō)過(guò)閉包函數(shù)有很多種類(lèi):

用戶(hù)綁定時(shí)提供的直接提供實(shí)現(xiàn)類(lèi)的方式:

$app->singleton("auth",function($app){
    return new AuthManager($app)
});//對(duì)象類(lèi)直接實(shí)現(xiàn)方法

這種情況 concrete(this) 直接就可以解析構(gòu)造出具體實(shí)現(xiàn)類(lèi),服務(wù)容器解析完畢。

用戶(hù)綁定時(shí)提供的帶有依賴(lài)注入的實(shí)現(xiàn):

$app->singleton(EloquentFactory::class, function ($app) {
    return EloquentFactory::construct(
        $app->make(FakerGenerator::class), database_path("factories")
);//對(duì)象類(lèi)依賴(lài)注入

這種情況下,concrete(this) 會(huì)轉(zhuǎn)而去解析 FakerGenerator::class,遞歸調(diào)用 make 函數(shù)。

bind函數(shù)使用 getClosure 包裝而來(lái):

function($container, $parameters = []){
    method = make/build;
    return $container->$method($concrete, $parameters);
}

這種情況,concrete(this) 將會(huì)繼續(xù)遞歸調(diào)用 make 或者 build。

反射

當(dāng) build 的參數(shù)是類(lèi)名而不是閉包的時(shí)候,就要利用反射構(gòu)建類(lèi)對(duì)象,如果構(gòu)建的類(lèi)對(duì)象不需要依賴(lài)任何其他參數(shù),那么:

$reflector = new ReflectionClass($concrete);
$constructor = $reflector->getConstructor();
if (is_null($constructor)) {
    return new $concrete;
}

如果需要依賴(lài)注入,那么就要用反射機(jī)制來(lái)獲取 __construct 函數(shù)所需要注入的依賴(lài),如果在make的時(shí)候帶入?yún)?shù)值,那么直接利用傳入的參數(shù)值;如果依賴(lài)是類(lèi)對(duì)像,那么遞歸調(diào)用 make 函數(shù);如果依賴(lài)是變量值,那么就從上下文中或者參數(shù)默認(rèn)值中去獲?。?/p>

...
$dependencies = $constructor->getParameters();
$instances = $this->resolveDependencies($dependencies);
...
     
protected function resolveDependencies(array $dependencies)
{
    $results = [];

    foreach ($dependencies as $dependency) {
      
      if ($this->hasParameterOverride($dependency)) {
          $results[] = $this->getParameterOverride($dependency);
               
          continue;
      }
      
      $results[] = is_null($class = $dependency->getClass())
                            ? $this->resolvePrimitive($dependency)
                            : $this->resolveClass($dependency);
      }

    return $results;
}

解析變量值參數(shù),如果變量值在上下文綁定中設(shè)置過(guò),則去取上下文綁定的值,否則通過(guò)反射去取參數(shù)默認(rèn)值,如果沒(méi)有默認(rèn)值,那么就要終止報(bào)錯(cuò):

protected function resolvePrimitive(ReflectionParameter $parameter)
{
      if (! is_null($concrete = $this->getContextualConcrete("$".$parameter->name))) {
          return $concrete instanceof Closure ? $concrete($this) : $concrete;
      }

      if ($parameter->isDefaultValueAvailable()) {
          return $parameter->getDefaultValue();
      }

      $this->unresolvablePrimitive($parameter);
}

protected function hasParameterOverride($dependency)
{
    return array_key_exists(
        $dependency->name, $this->getLastParameterOverride()
    );
}

protected function getParameterOverride($dependency)
{
    return $this->getLastParameterOverride()[$dependency->name];
}

protected function getLastParameterOverride()
{
    return count($this->with) ? end($this->with) : [];
}

解析類(lèi)參數(shù),利用服務(wù)容器進(jìn)行依賴(lài)注入:

protected function resolveClass(ReflectionParameter $parameter)
{
      try {
          return $this->make($parameter->getClass()->name);
      }
      catch (BindingResolutionException $e) {
          if ($parameter->isOptional()) {
              return $parameter->getDefaultValue();
          }

        throw $e;
      }
}
buildstack 解析棧

值的注意的是服務(wù)容器里面有個(gè) buildStack,每次利用反射對(duì)參數(shù)進(jìn)行依賴(lài)注入的時(shí)候,都要向這個(gè)數(shù)組中壓入當(dāng)前的解析對(duì)象,前面說(shuō)過(guò)這部分是為了上下文綁定而設(shè)計(jì)的:

...
$this->buildStack[] = $concrete;//壓入數(shù)組棧中
...
$instances = $this->resolveDependencies($dependencies);//解析依賴(lài)注入的參數(shù)
array_pop($this->buildStack);//彈出數(shù)組棧
...
解析標(biāo)簽

使用標(biāo)簽綁定的類(lèi),將會(huì)使用 tagged 來(lái)解析:

public function tagged($tag)
{
    $results = [];

    if (isset($this->tags[$tag])) {
        foreach ($this->tags[$tag] as $abstract) {
            $results[] = $this->make($abstract);
        }
    }

    return $results;
}
call方法注入

服務(wù)容器中,我們直接使用或者間接的使用 make 來(lái)構(gòu)造服務(wù)對(duì)象,但是在實(shí)際的應(yīng)用場(chǎng)景中,會(huì)有這樣的需求:我們擁有一個(gè)對(duì)象或者閉包函數(shù),想要調(diào)用它的一個(gè)函數(shù),但是它函數(shù)里面卻有其他類(lèi)的參數(shù),這個(gè)就需要進(jìn)行 call 方法注入

public function call($callback, array $parameters = [], $defaultMethod = null)
{
    return BoundMethod::call($this, $callback, $parameters, $defaultMethod);
}

在 上一篇 文章中,我們說(shuō)過(guò),call 函數(shù)中的 callback 參數(shù)有以下幾種形式:

閉包 Closure

class@method

類(lèi)靜態(tài)函數(shù),class::method

類(lèi)靜態(tài)函數(shù): [ className/classObj, method ];類(lèi)非靜態(tài)函數(shù): [ classObj, method ]

若 defaultMethod 不為空,className
首先,我們先看看 call 方法注入的流程圖:

從流程圖中我們可以看出來(lái),雖然調(diào)用 call 的形式有 5 種,但是實(shí)際最終的形式是三種,第二種和第五種被轉(zhuǎn)化為了第四種。
接下來(lái),我們?cè)敿?xì)的解析源碼:

call

先看一下 call 方法的主體:

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)
        );
    });
}

可以看出來(lái),call 方法注入主要有 4 個(gè)大的步驟:

對(duì)于 className@method 和 className-defaultMethod,實(shí)例化 className 為類(lèi)對(duì)象,轉(zhuǎn)化為 [ classObj, method ]。

判斷 [ classObj / classname, method ] 是否存在被綁定的方法,如果有則調(diào)用。

利用服務(wù)容器解析依賴(lài)的參數(shù)。

調(diào)用 call_user_func_array。

實(shí)例化類(lèi)對(duì)象

在這里 className@method 和 className-defaultMethod 兩種情況被轉(zhuǎn)化為 [ classObj, method ], className會(huì)被實(shí)例化為類(lèi)對(duì)象,并重新調(diào)用 call:

protected static function isCallableWithAtSign($callback)
{
    return is_string($callback) && strpos($callback, "@") !== false;
}
    
protected static function callClass($container, $target, array $parameters = [], $defaultMethod = null)
{
    $segments = explode("@", $target);

    $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
    );
} 
執(zhí)行綁定方法

針對(duì) [ className/classObj, method ], 調(diào)用被綁定的方法:

protected static function callBoundMethod($container, $callback, $default)
{
    if (! is_array($callback)) {
        return value($default);
    }

    $method = static::normalizeMethod($callback);

    if ($container->hasMethodBinding($method)) {
        return $container->callMethodBinding($method, $callback[0]);
    }

    return value($default);
}

protected static function normalizeMethod($callback)
{
    $class = is_string($callback[0]) ? $callback[0] : get_class($callback[0]);

    return "{$class}@{$callback[1]}";
}
    
public function hasMethodBinding($method)
{
    return isset($this->methodBindings[$method]);
}        

public function callMethodBinding($method, $instance)
{
    return call_user_func($this->methodBindings[$method], $instance, $this);
}

那么這個(gè)被綁定的方法 methodBindings 從哪里來(lái)呢,就是 上一篇 文章提的 bindMethod:

public function bindMethod($method, $callback)
{
    $this->methodBindings[$method] = $callback;
}

從上面可以看出來(lái),methodBindings 中 callback 參數(shù)一定是 classname@method 形式的。

實(shí)例化依賴(lài)

這一步就要通過(guò)反射來(lái)獲取函數(shù)方法需要注入的參數(shù)類(lèi)型,然后利用服務(wù)容器對(duì)參數(shù)類(lèi)型進(jìn)行解析構(gòu)建:

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);
}

getCallReflector 函數(shù)利用反射來(lái)獲取參數(shù)類(lèi)型,值得注意的是class::method是需要拆分處理的:

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);
}

利用傳入的參數(shù),利用服務(wù)容器構(gòu)建解析參數(shù)類(lèi)型,或者獲取參數(shù)默認(rèn)值:

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();
    }
}
call_user_func_array

關(guān)于這個(gè)函數(shù)可以參考 Laravel學(xué)習(xí)筆記之Callback Type

call_user_func_array(
            $callback, static::getMethodDependencies($container, $callback, $parameters)
        );

Written with StackEdit.

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/22965.html

相關(guān)文章

  • Laravel核心——Ioc服務(wù)容器源碼解析服務(wù)器綁定)

    摘要:服務(wù)容器的綁定綁定歡迎關(guān)注我的博客綁定是服務(wù)容器最常用的綁定方式,在上一篇文章中我們討論過(guò),的綁定有三種綁定自身綁定閉包綁定接口今天,我們這篇文章主要從源碼上講解服務(wù)容器是如何進(jìn)行綁定的。將閉包函數(shù)和單例變量存入數(shù)組中,以備解析時(shí)使用。 服務(wù)容器的綁定 bind 綁定 歡迎關(guān)注我的博客:www.leoyang90.cn bind 綁定是服務(wù)容器最常用的綁定方式,在 上一篇文章中我們討論...

    imtianx 評(píng)論0 收藏0
  • 深入剖析 Laravel 服務(wù)容器

    摘要:劃下重點(diǎn),服務(wù)容器是用于管理類(lèi)的依賴(lài)和執(zhí)行依賴(lài)注入的工具。類(lèi)的實(shí)例化及其依賴(lài)的注入,完全由服務(wù)容器自動(dòng)的去完成。 本文首發(fā)于 深入剖析 Laravel 服務(wù)容器,轉(zhuǎn)載請(qǐng)注明出處。喜歡的朋友不要吝嗇你們的贊同,謝謝。 之前在 深度挖掘 Laravel 生命周期 一文中,我們有去探究 Laravel 究竟是如何接收 HTTP 請(qǐng)求,又是如何生成響應(yīng)并最終呈現(xiàn)給用戶(hù)的工作原理。 本章將帶領(lǐng)大...

    abson 評(píng)論0 收藏0
  • Laravel思維導(dǎo)圖之Laravel核心概念

    摘要:的核心概念包括服務(wù)容器服務(wù)提供者門(mén)面契約。所有服務(wù)提供者都需要繼承類(lèi)??梢詾榉?wù)提供者的方法設(shè)置類(lèi)型提示。方法將在所有其他服務(wù)提供者均已注冊(cè)之后調(diào)用。同樣會(huì)整理成思維導(dǎo)圖的形式以方便記憶與回顧。 showImg(https://segmentfault.com/img/remote/1460000010771201); Laravel 的核心概念包括:服務(wù)容器、服務(wù)提供者、門(mén)面(Fac...

    wthee 評(píng)論0 收藏0
  • 為什么我們需要 Laravel IoC 容器?

    摘要:哲學(xué)的一個(gè)重要組成部分就是容器,也可以稱(chēng)為服務(wù)容器。那我們要怎么做呢請(qǐng)看下面的例子數(shù)據(jù)庫(kù)連接通過(guò)上面的代碼,如果我們想把改成,根本不需要去修改類(lèi)構(gòu)造函數(shù)里的依賴(lài)?,F(xiàn)在我要講下容器里到底發(fā)生了什么。 showImg(https://segmentfault.com/img/remote/1460000018868909); IOC 容器是一個(gè)實(shí)現(xiàn)依賴(lài)注入的便利機(jī)制 - Taylor?Ot...

    xiaokai 評(píng)論0 收藏0
  • Laravel中的核心概念

    摘要:可以為服務(wù)提供者的方法設(shè)置類(lèi)型提示。方法將在所有其他服務(wù)提供者均已注冊(cè)之后調(diào)用。所有服務(wù)提供者都在配置文件中注冊(cè)。可以選擇推遲服務(wù)提供者的注冊(cè),直到真正需要注冊(cè)綁定時(shí),這樣可以提供應(yīng)用程序的性能。 本文最早發(fā)布于 Rootrl的Blog 導(dǎo)言 Laravel是一款先進(jìn)的現(xiàn)代化框架,里面有一些概念非常重要。在上手Laravel之前,我認(rèn)為先弄懂這些概念是很有必要的。你甚至需要重溫下PHP...

    ddongjian0000 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<