PHP 依赖注入实现

分类: 源代码 > PHP

定义Demo类

<?php
class C
{
	public function doSomething() {
		echo __METHOD__, '我是C类<br />';
	}
}

class B
{
	private $c;

	public function __construct(C $c) {
		$this->c = $c;
	}

	public function doSomething() {
		$this->c->doSomething();
		echo __METHOD__, '我是B类<br />';
	}
}

class A
{
	private $b;
	private $d;

	public function __construct(B $b, $d) {
		$this->b = $b;
		$this->d = $d;
	}

	public function doSomething() {
		$this->b->doSomething();
		echo __METHOD__, '我是A类<br />';
		echo $this->d;
	}
}    

依赖注入实现:

/************************ 依赖注入 Start *************************
class YiLaiZhuRu
{
	private $s = array();

	function __set($k, $c)
	{
		$this->s[$k] = $c;
	}

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

echo '依赖注入:<br/>';
$class = new YiLaiZhuRu();
$class->c = function() {
	return new C();
};
$class->b = function($class) {
	return new B($class->c);
};
$class->a = function($class) {
	return new A($class->b);
};
$class->a->doSomething();
/************************ 依赖注入 End *************************/

容器实现:

/************************ 容器 Start *************************
class Ioc
{
	protected static $register = array();

	public static function bind($name, Callable $callback)
	{
		static::$register[$name] = $callback;
	}

	public static function make($name)
	{
		if (isset(static::$register[$name])) {
			$callback = static::$register[$name];
			return $callback();
		}
	}
}

echo '<br />容器:<br/>';
Ioc::bind('c', function()
{
	return new C();
});
Ioc::bind('b', function()
{
	return new B(Ioc::make('c'));
});
Ioc::bind('a', function()
{
	return new A(Ioc::make('b'));
});
Ioc::make('a')->doSomething();
/************************ 容器 End *************************/

高级容器实现

/************************ 高级容器 Start *************************/
/**
 * 依赖注入容器的高级功能
 * 真实的dependency injection container会提供更多的特性,如
 * 自动绑定(AutoWiring)或 自动解析(Automatic Resolution)
 * 注释解析器(Annotations)
 * 延迟注入(Lazy injection)
 */
class Container
{
	private $register = array();
	private $params = array();

	public function __set($k, $c)
	{
		if (is_string($c)) {
			$this->register[$k] = $c;
			$this->params[$k] = [];
		} elseif (is_array($c)) {
			$this->register[$k] = $c['class'];
			$this->params[$k] = $c['param'];
		}
	}

	public function __get($k)
	{
		try {
			return $this->build($this->register[$k], $this->params[$k]);
		}
		catch (exception $e) {
			dump($e);
		}
	}

	/**
	 * 自动绑定(Autowiring)自动解析(Automatic Resolution)
	 *
	 * @param string $className
	 * @param string $classParam
	 * @return object
	 * @throws Exception
	 */
	public function build($className, $classParam = [])
	{
		// 如果是匿名函数(Anonymous functions),也叫闭包函数(closures)
		if ($className instanceof Closure) {
			// 执行闭包函数,并将结果
			return $className($this);
		}

		/** @var ReflectionClass $reflector */
		$reflector = new ReflectionClass($className);

		// 检查类是否可实例化, 排除抽象类abstract和对象接口interface
		if (!$reflector->isInstantiable()) {
			throw new Exception("Can't instantiate this.");
		}

		/** @var ReflectionMethod $constructor 获取类的构造函数 */
		$constructor = $reflector->getConstructor();

		// 若无构造函数,直接实例化并返回
		if (is_null($constructor)) {
			return new $className;
		}

		// 取构造函数参数,通过 ReflectionParameter 数组返回参数列表
		$parameters = $constructor->getParameters();

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

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

	/**
	 * @param array $parameters
	 * @return array
	 * @throws Exception
	 */
	public function getDependencies($parameters, $classParam = [])
	{
		$dependencies = [];

		/** @var ReflectionParameter $parameter */
		foreach ($parameters as $parameter) {
			/** @var ReflectionClass $dependency */
			$dependency = $parameter->getClass();

			if (is_null($dependency)) {
				// 是变量,有默认值则设置默认值
				$dependencies[] = $this->resolveNonClass($parameter, $classParam);
			} else {
				// 是一个类,递归解析
				$dependencies[] = $this->build($dependency->name);
			}
		}

		return $dependencies;
	}

	/**
	 * @param ReflectionParameter $parameter
	 * @return mixed
	 * @throws Exception
	 */
	public function resolveNonClass($parameter, $classParam)
	{
		// 有默认值则返回默认值
		if ($parameter->isDefaultValueAvailable()) {
			return $parameter->getDefaultValue();
		} elseif ($classParam[$parameter->getName()]) {
			return $classParam[$parameter->getName()];
		}

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

echo '<br />高级容器:</br />';
$di = new Container();
//    $di->a = 'A';
$di->a = [
	'class' => 'A',
	'param' => [
		'd' => function() {echo 1;}
	]
];

$model = $di->a;
$model->doSomething();
/************************ 高级容器 End *************************/
来源:原创 发布时间:2022-07-13 12:27:03