php依赖注入容器2

上一篇文章中,我们了解了什么是依赖注入,依赖注入有什么有点,以及一个简单的实现。
本篇文章,我们来优化一下 容器,使他更加的智能,以及优雅。

示例代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
//对 Container 类进行优化

class Container {
private $s = array();
public function __set($k, $c)
{
$this->s[$k] = $c;
}

public function __get($k)
{
//return $this->s[$k]($this);

return $this->build($this->s[$k]);
}

//自动绑定,自动解析
public function build($className)
{
//是否是闭包函数
if($className instanceof Closure)
{
return $className($this);
}

//使用反射类来操作
$reflector = new ReflectionClass($className);
//检查类是否可以进行实例话,排除 抽象类(abstract) 和 接口(interface)
if(!$reflector->isInstantiable()){
throw new Exception("Can't instantiate class".$className, 1);
}

//获取类的构造函数
$constructor = $reflector->getConstructor();
//
if(is_null($constructor)){
return new $className;
}

//获取构造函数参数
$params = $constructor->getParameters();

//递归解析构造函数的参数
$dependencies = $this->getDependencies($params);

//创建一个新的实例,给出的参数传递到类的构造函数
return $reflector->newInstanceArgs($dependencies);
}

//获取构造函数的参数
public function getDependencies($params)
{
$dependencies = [];
foreach ($params as $param) {
$dependency = $param->getClass();
//不是类,是变量,有默认值则设置默认值
if(is_null($dependency)){
$dependencies[] = $this->resolveNonClass($param);
} else {
//是一个类,则递归解析
$dependencies[] = $this->build($dependency->name);
}
}

return $dependencies;
}

//获取构造函数中的默认值
public function resolveNonClass($param)
{
//有默认值则返回默认
if($param->isDefaultValueAvailable()){
return $param->getDefaultValue();
}

throw new Exception("I have no idea what to do here.", 1);
}
}

调用代码

1
2
3
4
5
6
7
8
9
10
11
<?php 
$c = new Container();

$c -> a = 'A';

$c->a->message();

//print
//辣鸡,没有我你们行不
//哈哈,你离不开我吧
//卑微小A[Finished in 0.0s]

这里,我们可以看到,调用A的的时候更加的方便了,我们需要再A的构造函数中定义好我们需要的类。Container 就可以根据我们的构造函数自动加载我们所需要的依赖。

tips: Container类中,使用了 PHP 类的反射。有兴趣的朋友可以了解一下。

  • Copyright: Copyright is owned by the author. For commercial reprints, please contact the author for authorization. For non-commercial reprints, please indicate the source.

请我喝杯咖啡吧~