不积跬步无以至千里不积小流无以成江海
反射机制的强大在于,在很多情况下可以使代码更加高效
例如不知道事先需要实例化哪个类,而是在运行时根据动态信息确定
对于这种情况可以通过反射机制获取需要实例类的构造函数信息并完成相应的实例化
class A
{
public function call()
{
echo 'hello world';
}
}
// ReflectionClass 类报告了一个类的有关信息
$ref = new ReflectionClass('A');
// ReflectionClass::newInstanceArgs — 从给出的参数创建一个新的类实例
$inst = $ref->newInstanceArgs();
$inst->call();
laravel框架中,服务容器解析服务的过程中就用到了反射机制
// 根据给定的类初始化一个具体事例
public function build($concrete, array $parameters = [])
{
/*
* 解析服务是通过build()函数实现的
* 查找对应的服务是否被服务提供者注册为实例或提供服务的匿名函数
* 如果是则直接进行服务解析
*/
if ($concrete instanceof Closure) {
return $concrete($this, $parameters);
}
/*
* 如果服务名称没有相应的服务绑定,通过反射机制来动态创建服务
*/
// 创建一个反射实例,$concrete是类的名称
$reflector = new ReflectionClass($concrete);
// 检查类是否可实例化
if (!$reflector->isInstantiable()) {
$message = "Target [$concrete] is not instantiable .";
throw new BindingResolutionContractException($message);
}
$this->buildStack[] = $concrete;
// 获取类的构造方法,当该类存在构造函数时,返回一个ReflecttionMethod对象,相当于获取构造函数的反射类
$constructor = $reflector->getConstructor();
// 如果不存在构造函数直接实例化该类
if (is_null($constructor)) {
array_pop($this->buildStack);
return new $concrete;
}
// 获取构造函数的依赖的输入参数
$dependencies = $constructor->getParameters();
// 获取直接提供的实参
$parameters = $this->keyParamtersByArgument($dependencies, $parameters);
// 未直接提供的实参
$instances = $this->getDependencies($dependencies, $parameters);
array_pop($this->buildStack);
// 从给出的参数创建一个新的类实例
return $reflector->newInstanceArgs($instances);
}
未完待续,继续更新......