解释Laravel容器依赖注入的实现的好文章

<?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
{
  /**
   *  容器绑定,用来装提供的实例或者 提供实例的回调函数
   * @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);
  }

  /**
   * 默认生成实例的回调闭包
   *
   * @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;
  }

  /**
   * 获取绑定的回调函数
   */
  public function getConcrete($abstract)
  {
    if(! isset($this->building[$abstract])){
      return $abstract;
    }

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

  /**
   * 判断 是否 可以创建服务实体
   */
  public function isBuildable($concrete, $abstract)
  {
    return $concrete === $abstract || $concrete instanceof Closure;
  }

  /**
   * 根据实例具体名称实例具体对象
   */
  public function build($concrete)
  {
    if($concrete instanceof Closure){
      return $concrete($this);
    }

    //创建反射对象
    $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);

  }

  //通过反射解决参数依赖
  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');
//通过容器实现依赖注入,完成类的实例化;
$people = $app->make('People');
//调用方法
echo $people->putDog();

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容