Skip to content

分析一下get方法源码,

php
public function get($id)
{
    // 如果解析过,则直接返回
    if (isset($this->resolvedEntries[$id]) || array_key_exists($id, $this->resolvedEntries)) {
        return $this->resolvedEntries[$id];
    }
    return $this->resolvedEntries[$id] = $this->make($id);
}

上面可以看出,首次解析不走if,查看make方法,

php
public function make(string $name, array $parameters = [])
{
    $definition = $this->getDefinition($name);
    if (! $definition) {
        throw new NotFoundException("No entry or class found for '{$name}'");
    }

    return $this->resolveDefinition($definition, $parameters);
}

前面绑定阶段,已经将ApplicationInterface绑定到Hyperf\Framework\ApplicationFactory类上,通过DefinitionSource类,将对应实现转换成对应DefinitionInterface接口的实现类。

php
// 调用逻辑
public function __construct(array $source)
{
    $this->source = $this->normalizeSource($source);
}

protected function normalizeSource(array $source): array
{
    $definitions = [];
    foreach ($source as $identifier => $definition) {
        $normalizedDefinition = $this->normalizeDefinition($identifier, $definition);
        if (! is_null($normalizedDefinition)) {
            $definitions[$identifier] = $normalizedDefinition;
        }
    }
    return $definitions;
}

protected function normalizeDefinition(string $identifier, $definition): ?DefinitionInterface
{
    if ($definition instanceof PriorityDefinition) {
        $definition = $definition->getDefinition();
    }


    if (is_string($definition) && class_exists($definition)) {
        if (method_exists($definition, '__invoke')) {
            return new FactoryDefinition($identifier, $definition, []);
        }
        return $this->autowire($identifier, new ObjectDefinition($identifier, $definition));
    }

    if (is_callable($definition)) {
        return new FactoryDefinition($identifier, $definition, []);
    }

    return null;
}

查看ApplicationFactory类,存在__invoke方法,返回的是一个FactoryDefinition对象。 ![](image https://oss.xiaokeaii.top/2024/applicationFactory.png)

php
$definition = $this->getDefinition($name);

所以这行返回的是一个FactoryDefinition对象。打印结果如下, ![](image https://oss.xiaokeaii.top/2024/工厂定义.png )

resolveDefinition方法

继续分析,查看resolveDefinition方法,

文件位置: /vendor/hyperf/di/src/Container.php

php
protected function resolveDefinition(DefinitionInterface $definition, array $parameters = [])
{
    return $this->definitionResolver->resolve($definition, $parameters);
}

上面可以看到,这里调用了解析调度器ResolverDispatcherresolve方法。

resolve方法

文件位置:/vendor/hyperf/di/src/Resolver/ResolverDispatcher.php

php
public function resolve(DefinitionInterface $definition, array $parameters = [])
{
    if ($definition instanceof SelfResolvingDefinitionInterface) {

        return $definition->resolve($this->container);
    }
    $guard = DepthGuard::getInstance();

    return $guard->call(
        $definition->getName(),
        fn () => $this->getDefinitionResolver($definition)->resolve($definition, $parameters)
    );
}

这里FactoryDefinition不是SelfResolvingDefinitionInterface接口的实现类,所以不走if$guardDepthGuard类的实例,调用call方法,

call方法

文件位置:/vendor/hyperf/di/src/Resolver/DepthGuard.php

php
public function call(string $name, callable $callable)
{
    try {
        $this->increment();
        return $callable();
    } catch (CircularDependencyException $exception) {
        $exception->addDefinitionName($name);
        throw $exception;
    } finally {
        $this->decrement();
    }
}

这里最终执行传入的闭包,回到上面,执行闭包。 查看闭包执行源码,

./vendor/hyperf/di/src/Resolver/ResolverDispatcher.php

getDefinitionResolver方法
php
private function getDefinitionResolver(DefinitionInterface $definition): ResolverInterface
{
    return match (true) {
        $definition instanceof ObjectDefinition => $this->objectResolver ??= new ObjectResolver($this->container, $this),
        $definition instanceof FactoryDefinition => $this->factoryResolver ??= new FactoryResolver($this->container, $this),
        default => throw new RuntimeException('No definition resolver was configured for definition of type ' . get_class($definition)),
    };
}

从代码可知,这里会根据DefinitionInterface的实现类,将对应解析器赋值给成员变量。 这里传进来的是FactoryDefinition类,所以会执行第二条。 紧接着调用FactoryResolver类的resolve方法。

resolve方法

文件位置:/vendor/hyperf/di/src/Resolver/FactoryResolver.php

php
public function resolve(DefinitionInterface $definition, array $parameters = [])
{
    $callable = null;
    try {
        $callable = $definition->getFactory();
        if (! method_exists($callable, '__invoke')) {
            throw new NotCallableException();
        }
        if (is_string($callable)) {
            $callable = $this->container->get($callable);
        }
        return $callable($this->container, $parameters);
    } catch (NotCallableException $e) {
        // Custom error message to help debugging
        if (is_string($callable) && class_exists($callable) && method_exists($callable, '__invoke')) {
            throw new InvalidDefinitionException(sprintf('Entry "%s" cannot be resolved: factory %s. Invokable classes cannot be automatically resolved if autowiring is disabled on the container, you need to enable autowiring or define the entry manually.', $definition->getName(), $e->getMessage()));
        }

        throw new InvalidDefinitionException(sprintf('Entry "%s" cannot be resolved: factory %s', $definition->getName(), $e->getMessage()));
    }
}

分析该方法,$callable是工厂的类名,如果传递过来的是字符串,则通过容器解析出对应的类,方法同理,不再赘述。 最终调用该工厂类的__invoke方法返回解析结果。