解释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();

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 196,264评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,549评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 143,389评论 0 325
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,616评论 1 267
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,461评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,351评论 1 273
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,776评论 3 387
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,414评论 0 255
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,722评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,760评论 2 314
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,537评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,381评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,787评论 3 300
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,030评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,304评论 1 252
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,734评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,943评论 2 336

推荐阅读更多精彩内容