通过上一节的注解解析后,swoft将获取到的注解对象解析成了定义对象,实现了对这些原始注解对象的梳理工作.

本大节将梳理获取到的这些定义对象的解析.

解析定义对象的入口办法:

private function parseDefinitions(): void{     // 实例化解析器,将后面解析好的数据传递进去     $annotationParser = new DefinitionObjParser(         $this->definitions,         $this->objectDefinitions,         $this->classNames,         $this->aliases     );     // 调用解析器的解析办法     // Collect info     $definitionData = $annotationParser->parseDefinitions();     // 将返回的后果保留在容器上     [$this->definitions, $this->objectDefinitions, $this->classNames, $this->aliases] = $definitionData;}

解析器的入口办法:

public function parseDefinitions(): array{     // 遍历bean配置,失去bean名称和配置(定义)     foreach ($this->definitions as $beanName => $definition) {         // 如果曾经通过上一节的注解解析,生成了这个定义对象         if (isset($this->objectDefinitions[$beanName])) {             // 获取这个定义对象             $objectDefinition = $this->objectDefinitions[$beanName];             // 重置这个定义对象             $this->resetObjectDefinition($beanName, $objectDefinition, $definition);             // 持续下一个             continue;          }         // 否则,依据bean配置创立定义对象         $this->createObjectDefinition($beanName, $definition);     }     return [$this->definitions, $this->objectDefinitions, $this->classNames, $this->aliases];}

重置定义对象:

private function resetObjectDefinition(string $beanName, ObjectDefinition $objDefinition, array $definition): void{     // 获取bean配置中定义的类名     // Parse class name     $className = $definition['class'] ?? '';     // 获取定义对象的类名     $objClassName = $objDefinition->getClassName();     // 如果配置中定义了类名且与定义对象中的类名不同,抛出异样     if (!empty($className) && $className !== $objClassName) {        throw new InvalidArgumentException('Class for annotations and definitions must be the same Or not to define class');     }     // 更新定义对象     $objDefinition = $this->updateObjectDefinitionByDefinition($objDefinition, $definition);     // 将更新后的定义对象设置回定义对象池     $this->objectDefinitions[$beanName] = $objDefinition;}

更新定义对象办法:

private function updateObjectDefinitionByDefinition(ObjectDefinition $objDfn, array $definition): ObjectDefinition{     // 将bean配置解析成结构参数注入对象、属性注入对象数组、选项数组     [$constructInject, $propertyInjects, $option] = $this->parseDefinition($definition);     // 设置结构注入     // Set construct inject     if (!empty($constructInject)) {        $objDfn->setConstructorInjection($constructInject);     }     // 遍历属性注入数组并设置到定义对象中     // Set property inject     foreach ($propertyInjects as $propertyName => $propertyInject) {        // 设置属性注入对象        // 如果曾经有这个属性的设置,则回被笼罩        $objDfn->setPropertyInjection($propertyName, $propertyInject);     }     // 类型数组     $scopes = [         Bean::SINGLETON,         Bean::PROTOTYPE,         Bean::REQUEST,     ];     // 获取选项中的类型定义     $scope = $option['scope'] ?? '';     // 获取选项中的别名定义     $alias = $option['alias'] ?? '';     // 也就是说不能在这里定义session类型     if (!empty($scope) && !in_array($scope, $scopes, true)) {        throw new InvalidArgumentException('Scope for definition is not undefined');     }     // 设置类型     // Update scope     if (!empty($scope)) {        $objDfn->setScope($scope);     }     // 更新别名     // 感觉这里的代码是有问题的     // 获取对象原始别名和删除别名映射的操作是不是应该放在     // 设置操作的后面?     // 否则这一步操作就等于没有删除后面定义的别名     // 且设置了新的别名     // Update alias     if (!empty($alias)) {         // 设置定义对象的别名         $objDfn->setAlias($alias);         // 获取定义对象别名         $objAlias = $objDfn->getAlias();         unset($this->aliases[$objAlias]);         // 设置新的别名         $this->aliases[$alias] = $objDfn->getName();     }     // 返回曾经更新的定义对象     return $objDfn;}

bean配置解析:

private function parseDefinition(array $definition): array{     // Remove class key     // 移除类名的定义     unset($definition['class']);          // Parse construct     // 获取结构参数     $constructArgs = $definition[0] ?? [];     if (!is_array($constructArgs)) {        throw new InvalidArgumentException('Construct args for definition must be array');     }          // Parse construct args     $argInjects = [];     // 遍历结构参数     foreach ($constructArgs as $arg) {         // 获取参数的理论值和是否为援用         [$argValue, $argIsRef] = $this->getValueByRef($arg);         // 创立注入的结构参数         $argInjects[] = new ArgsInjection($argValue, $argIsRef);     }          // Set construct inject     $constructInject = null;     如果须要注入的结构参数不为空     if (!empty($argInjects)) {        // 创立__construct的注入办法        $constructInject = new MethodInjection('__construct', $argInjects);     }     // 移除结构参数的定义     // Remove construct definition     unset($definition[0]);     // 解析配置中的__option局部     // Parse definition option     $option = $definition['__option'] ?? [];     if (!is_array($option)) {        throw new InvalidArgumentException('__option for definition must be array');     }     // 移除__option的配置     // Remove `__option`     unset($definition['__option']);     // 解析属性配置     // Parse definition properties     $propertyInjects = [];     // 遍历残余的所有配置     foreach ($definition as $propertyName => $propertyValue) {         // 如果属性名不是字符串,则报错         if (!is_string($propertyName)) {            throw new InvalidArgumentException('Property key from definition must be string');         }         // 获取属性值和类型         [$proValue, $proIsRef] = $this->getValueByRef($propertyValue);         // 如果属性是个数组,则再次遍历设置         // Parse property for array         if (is_array($proValue)) {            $proValue = $this->parseArrayProperty($proValue);         }         // 创立属性注入对象         $propertyInject = new PropertyInjection($propertyName, $proValue, $proIsRef);         // 保留属性注入对象         $propertyInjects[$propertyName] = $propertyInject;     }     return [$constructInject, $propertyInjects, $option];}

获取参数的理论值和是否援用:

protected function getValueByRef($value): array{     if (!is_string($value)) {        return [$value, false];     }     // Reg match     $isRef = preg_match('/^${(.*)}$/', $value, $match);     if ($isRef && isset($match[1])) {        return [$match[1], (bool)$isRef];     }     return [$value, false];}

创立新的定义对象:

private function createObjectDefinition(string $beanName, array $definition): void{     // 获取配置中定义的类名,不存在就报错     $className = $definition['class'] ?? '';     if (empty($className)) {        throw new InvalidArgumentException(sprintf('%s key for definition must be defined class', $beanName));     }     // 通过定义对象名称(beanName)和类名实例化新的定义对象     $objDefinition = new ObjectDefinition($beanName, $className);     // 更新定义对象     $objDefinition = $this->updateObjectDefinitionByDefinition($objDefinition, $definition);     // 将新的定义对象名增加到类名映射数组中     // 别名在updateObjectDefinitionByDefinition办法中曾经更新     $classNames = $this->classNames[$className] ?? [];     $classNames[] = $beanName;     $this->classNames[$className]       = array_unique($classNames);     // 保留定义对象     $this->objectDefinitions[$beanName] = $objDefinition;}

总结:

本大节的次要性能:    依据bean的配置信息,更新前一大节失去的定义对象,创立前一大节没有创立的定义对象.