zoukankan      html  css  js  c++  java
  • php 自动绑定di容器实现

      1 <?php
      2 
      3 class Bim
      4 {
      5     public function doSth()
      6     {
      7         echo __METHOD__.PHP_EOL;
      8     }
      9 }
     10 
     11 class Bar
     12 {
     13     protected $bim;
     14 
     15     public function __construct(Bim $bim)
     16     {
     17         $this->bim = $bim;
     18     }
     19 
     20     public function doSth()
     21     {
     22         $this->bim->doSth();
     23         echo __METHOD__.PHP_EOL;
     24     }
     25 }
     26 
     27 class Bar2 extends Bar
     28 {
     29     protected $bim;
     30 
     31     public function doSth()
     32     {
     33         $this->bim->doSth();
     34         echo __METHOD__.PHP_EOL;
     35     }
     36 }
     37 
     38 class Foo
     39 {
     40     private $bar;
     41 
     42     public function __construct(Bar $bar)
     43     {
     44         $this->bar = $bar;
     45     }
     46 
     47     public function doSth()
     48     {
     49         $this->bar->doSth();
     50         echo __METHOD__.PHP_EOL;
     51     }
     52 }
     53 
     54 class Container
     55 {
     56     private $s = [];
     57 
     58     public function __set($k, $c)
     59     {
     60         $this->s[$k] = $c;
     61     }
     62 
     63     public function __get($k)
     64     {
     65         return $this->s[$k]($this);
     66     }
     67 }
     68 
     69 class Container2
     70 {
     71     private $s = [];
     72 
     73     public function __set($k, $c)
     74     {
     75         $this->s[$k] = $c;
     76     }
     77 
     78     public function __get($k)
     79     {
     80         if (!$this->s[$k]) {
     81             return false;
     82         }    
     83         return $this->build($this->s[$k]);
     84     }
     85 
     86     public function build($className)
     87     {
     88         if ($className instanceof Closure) {
     89             return $className($this);
     90         }
     91 
     92         try {
     93             $reflector = new ReflectionClass($className);
     94         } catch (ReflectionException $e) {
     95             echo $className.'类反射异常'.PHP_EOL;
     96             echo $e->getMessage();
     97         }
     98         
     99         #检查类是否可实例化, 排除抽象类abstract和对象接口interface
    100         if (!$reflector->isInstantiable()) {
    101             throw new Exception("Can't instantiate this.");
    102         }
    103 
    104         $constructor = $reflector->getConstructor();
    105         
    106         #如果没有构造函数, 直接实例化并返回
    107         if (is_null($constructor)) {
    108             return new $className;
    109         }
    110 
    111         $parameters = $constructor->getParameters();
    112 
    113         #递归解析构造函数的参数
    114         $dependencies = $this->getDependencies($parameters);
    115 
    116         #创建一个类的新实例,给出的参数将传递到类的构造函数.
    117         return $reflector->newInstanceArgs($dependencies);
    118     }
    119 
    120     public function getDependencies($parameters)
    121     {
    122         $dependencies = [];
    123 
    124         foreach ($parameters as $parameter) {
    125             $dependency = $parameter->getClass();
    126 
    127             if (is_null($dependency)) {
    128                 $dependencies[] = $this->resolveNonClass($parameter);
    129             } else {
    130                 #是一个类,递归解析
    131                 $className = lcfirst($dependency->name);
    132                 #先取出容器中绑定的类 否则自动绑定
    133                 if ($this->s[$className]) {
    134                     $dependencies[] = $this->$className;                    
    135                 } else {
    136                     $dependencies[] = $this->build($dependency->name);                                        
    137                 }
    138             }
    139         }
    140 
    141         return $dependencies;
    142     }
    143 
    144     public function resolveNonClass($parameter)
    145     {
    146         // 有默认值则返回默认值
    147         if ($parameter->isDefaultValueAvailable()) {
    148             return $parameter->getDefaultValue();
    149         }
    150         throw new Exception('I have no idea what to do here.');
    151     }
    152 }
    153 
    154 // 依赖注入模式
    155 //$foo = new Foo(new Bar(new Bim()));
    156 
    157 #di模式
    158 // $c = new Container();
    159 // $c->bim = function() {
    160 //     return new Bim();
    161 // };
    162 // $c->bar = function($c) {
    163 //     return new Bar($c->bim);
    164 // };
    165 // $c->foo = function($c) {
    166 //     return new Foo($c->bar);
    167 // };
    168 
    169 #实现了自动绑定
    170 #1向di中注册类
    171 $c = new Container2();
    172 $c->bim = 'Bim';
    173 #$c->bar = 'Bar2'; #实现了自动绑定 如果没有注册类的化就按自动加载去寻找类
    174 $c->foo = 'Foo';
    175 // $c->bar = 'Bar';
    176 // $c->foo = function ($c) {
    177 //     return new Foo($c->bar);
    178 // };
    179 // 从容器中取得Foo
    180 $foo = $c->foo;
    181 $foo->doSth();

    参考:https://segmentfault.com/a/1190000002424023

  • 相关阅读:
    和远哥一起了解Hadoop的MapReduce是如何运行的
    远哥跟你说 Spring的 classpath 通配符加载配置文件
    远哥Amoeba源码分析之:核心类说明
    远哥推荐:面向网络的数据库 Neo4j
    Hadoop 1.0.3 在CentOS 6.2上安装过程 [个人安装通过的全程记录]
    OpenShift 添加 URL Rewrite 重写支持
    Access中空值处理
    解决EOS启动“不能连接到Server”的问题
    [原创]用递归写的一个object 转换成JSON的函数
    JSON反序列的问题原因查找
  • 原文地址:https://www.cnblogs.com/a-flydog/p/6134560.html
Copyright © 2011-2022 走看看