laravel学习之IOC容器分析(二)
在laravel学习之IOC容器分析(一)中,曾经提到过在
$this->registerBaseServiceProviders();
if ($this->booted) {
$this->bootProvider($provider);
}
boorProvider()里面有用call方法来解决服务提供器的依赖问题,那我们就来研究一下这个call()方法
protected function bootProvider(ServiceProvider $provider)
{
if (method_exists($provider, 'boot')) {
return $this->call([$provider, 'boot']);
}
}
先判断这个服务提供器里面是否有boot这个方法,有的话调用就调用call方法。
/**
* Call the given Closure / class@method and inject its dependencies.
*
* @param callable|string $callback
* @param array $parameters
* @param string|null $defaultMethod
* @return mixed
*/
public function call($callback, array $parameters = [], $defaultMethod = null)
{
if ($this->isCallableWithAtSign($callback) || $defaultMethod) {
return $this->callClass($callback, $parameters, $defaultMethod);
}
$dependencies = $this->getMethodDependencies($callback, $parameters);
return call_user_func_array($callback, $dependencies);
}
如果调用这个方法时传的值是这样的话call(ASeverProvider@a)的话,就会调用callClass方法
protected function callClass($target, array $parameters = [], $defaultMethod = null)
{
$segments = explode('@', $target);
// If the listener has an @ sign, we will assume it is being used to delimit
// the class name from the handle method name. This allows for handlers
// to run multiple handler methods in a single class for convenience.
$method = count($segments) == 2 ? $segments[1] : $defaultMethod;
if (is_null($method)) {
throw new InvalidArgumentException('Method not provided.');
}
return $this->call([$this->make($segments[0]), $method], $parameters);
}
把这个字符串拆分,判断是否有2个元素,有的话就把$method这个变量设为要调用的方法名,把第一个参数$segments[0]即例子中的ASeverProvider当作类名,然后再次调用call方法。
然后就来到了
protected function getMethodDependencies($callback, array $parameters = [])
{
$dependencies = [];
foreach ($this->getCallReflector($callback)->getParameters() as $parameter) {
$this->addDependencyForCallParameter($parameter, $parameters, $dependencies);
}
return array_merge($dependencies, $parameters);
}
里面调用了getCallReflector
protected function getCallReflector($callback)
{
if (is_string($callback) && strpos($callback, '::') !== false) {
$callback = explode('::', $callback);
}
if (is_array($callback)) {
return new ReflectionMethod($callback[0], $callback[1]);
}
return new ReflectionFunction($callback);
}
这里就是call方法解决依赖的根本了,这个方法运用了ReflectionMethod,这个是依靠php的反射机制实现的,所以
$this->getCallReflector($callback)->getParameters()
就是获取当前类boot方法的参数,也就是依赖注入的方法注入,然后就在下面添加到$dependencies数组中,然后就通过
call_user_func_array($callback, $dependencies)
放进当前类的boot方法中。
执行完后返回$provider,整过过程就是这样。
完....

浙公网安备 33010602011771号