解釋Laravel容器依賴注入的實現(xiàn)的好文章

<?php

/**
 * 動物
 */
class Dog{
  public function dogCall(){
    return '汪汪汪';
  }
}

/**
 * 擬人類
 */
class People
{
  public $dog = null;

  /**
   * People constructor.
   * @param Dog $dog
   */
  public function __construct(Dog $dog)
  {
    $this->dog = $dog;
  }

  /**
   * @return string
   */
  public function putDog(){
    return $this->dog->dogCall();
  }

}

class Container
{
  /**
   *  容器綁定,用來裝提供的實例或者 提供實例的回調(diào)函數(shù)
   * @var array
   */
  public $building = [];

  /**
   * 注冊一個綁定到容器
   */
  public function bind($abstract, $concrete = null, $shared = false)
  {
    if(is_null($concrete)){
      $concrete = $abstract;
    }

    if(!$concrete instanceOf Closure){
      $concrete = $this->getClosure($abstract, $concrete);
    }

    $this->building[$abstract] =  compact("concrete", "shared");
  }

  //注冊一個共享的綁定 單例
  public function singleton($abstract, $concrete, $shared = true){
    $this->bind($abstract, $concrete, $shared);
  }

  /**
   * 默認生成實例的回調(diào)閉包
   *
   * @param $abstract
   * @param $concrete
   * @return Closure
   */
  public function getClosure($abstract, $concrete)
  {
    return function($c) use($abstract, $concrete){
      $method = ($abstract == $concrete)? 'build' : 'make';

      return $c->$method($concrete);
    };
  }

  /**
   * 生成實例
   */
  public function make($abstract)
  {
    $concrete = $this->getConcrete($abstract);

    if($this->isBuildable($concrete, $abstract)){
      $object = $this->build($concrete);
    }else{
      $object = $this->make($concrete);
    }

    return $object;
  }

  /**
   * 獲取綁定的回調(diào)函數(shù)
   */
  public function getConcrete($abstract)
  {
    if(! isset($this->building[$abstract])){
      return $abstract;
    }

    return $this->building[$abstract]['concrete'];
  }

  /**
   * 判斷 是否 可以創(chuàng)建服務實體
   */
  public function isBuildable($concrete, $abstract)
  {
    return $concrete === $abstract || $concrete instanceof Closure;
  }

  /**
   * 根據(jù)實例具體名稱實例具體對象
   */
  public function build($concrete)
  {
    if($concrete instanceof Closure){
      return $concrete($this);
    }

    //創(chuàng)建反射對象
    $reflector = new ReflectionClass($concrete);

    if( ! $reflector->isInstantiable()){
      //拋出異常
      throw new \Exception('無法實例化');
    }

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

    $dependencies = $constructor->getParameters();
    $instance = $this->getDependencies($dependencies);

    return $reflector->newInstanceArgs($instance);

  }

  //通過反射解決參數(shù)依賴
  public function getDependencies(array $dependencies)
  {
    $results = [];
    foreach( $dependencies as $dependency ){
      $results[] = is_null($dependency->getClass())
        ?$this->resolvedNonClass($dependency)
        :$this->resolvedClass($dependency);
    }

    return $results;
  }

  //解決一個沒有類型提示依賴
  public function resolvedNonClass(ReflectionParameter $parameter)
  {
    if($parameter->isDefaultValueAvailable()){
      return $parameter->getDefaultValue();
    }
    throw new \Exception('出錯');

  }

  //通過容器解決依賴
  public function resolvedClass(ReflectionParameter $parameter)
  {
    return $this->make($parameter->getClass()->name);

  }

}

//$man = new People(new Dog());
//echo $man->putDog();

//實例化容器類
$app =  new Container();
//向容器中填充Dog
$app->bind('Dog','Dog');
//填充People
$app->bind('People', 'People');
//通過容器實現(xiàn)依賴注入,完成類的實例化;
$people = $app->make('People');
//調(diào)用方法
echo $people->putDog();

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容