经过上一节的注解分析,swoft将得到的注解对象解析为定义对象,完成对这些原始注解对象的梳理工作。本节将对得到的这些定义对象的分析进行梳理。解析定义对象入口方法:privatefunctionparseDefinitions():void{//实例化解析器并传入之前解析的数据$annotationParser=newDefinitionObjParser($this->definitions,$this->objectDefinitions,$this->classNames,$this->别名);//调用解析器的解析方法//收集信息$definitionData=$annotationParser->parseDefinitions();//将返回的结果保存在容器上[$this->definitions,$this->objectDefinitions,$this->classNames,$this->aliases]=$definitionData;}解析器的入口方法:publicfunctionparseDefinitions():array{//遍历bean的配置,得到bean的名称和配置(定义)foreach($this->definitionsas$beanName=>$definition){//如果上一节的注解已经解析,this定义对象已经生成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];}重置定义对象:privatefunctionresetObjectDefinition(string$beanName,ObjectDefinition$objDefinition,array$definition):void{//获取bean配置中定义的类名//解析类名$className=$definition['class']??'';//获取定义对象的类名$objClassName=$objDefinition->getClassName();//如果配置中定义了类名,与定义对象中的类名不同,则抛出异常if(!empty($className)&&$className!==$objClassName){thrownewInvalidArgumentException('注解类和定义类必须相同或不定义类');}//更新定义对象$objDefinition=$this->updateObjectDefinitionByDefinition($objDefinition,$definiti在);//将更新后的定义对象设置回定义对象池$this->objectDefinitions[$beanName]=$objDefinition;}更新定义对象方法:privatefunctionupdateObjectDefinitionByDefinition(ObjectDefinition$objDfn,array$definition):ObjectDefinition{//解析bean配置成构造参数注入对象,属性注入对象数组,选项数组[$constructInject,$propertyInjects,$option]=$this->parseDefinition($definition);//设置构造注入//设置构造注入if(!empty($constructInject)){$objDfn->setConstructorInjection($constructInject);}//遍历属性注入数组并设置为定义对象//设置属性注入foreach($propertyInjectsas$propertyName=>$propertyInject){//设置属性注入对象//如果该属性已经被设置,将被覆盖$objDfn->setPropertyInjection($propertyName,$propertyInject);}//类型数组$scopes=[Bean::SINGLETON,Bean::PROTOTYPE,Bean::REQUEST,];//获取选项中的类型定义$scope=$option['scope']??'';//获取选项中的别名定义$alias=$option['alias']??'';//也就是说这里不能定义session类型}//设置类型//更新范围if(!empty($scope)){$objDfn->setScope($scope);}//更新别名//感觉这里的代码有问题//获取对象原来的别名和删除别名映射的操作是否应该放在//设置操作的前面?//否则,这一步相当于不删除之前定义的别名//并设置一个新的别名//Updatealiasif(!empty($alias)){//设置定义对象的别名$objDfn->setAlias($别名);//获取定义对象的别名$objAlias=$objDfn->getAlias();取消设置($this->aliases[$objAlias]);//设置一个新别名$this->aliases[$alias]=$objDfn->getName();}//返回更新后的定义对象return$objDfn;}bean配置分析:privatefunctionparseDefinition(array$definition):array{//移除classkey//移除定义的类名unset($definition['class']);//解析构造//获取构造参数$constructArgs=$d定义[0]??[];if(!is_array($constructArgs)){thrownewInvalidArgumentException('Constructargsfordefinitionmustbearray');}//解析构造参数$argInjects=[];//遍历构造参数foreach($constructArgsas$arg){//获取参数的实际值以及是否为引用[$argValue,$argIsRef]=$this->getValueByRef($arg);//创建注入构造参数$argInjects[]=newArgsInjection($argValue,$argIsRef);}//设置构造注入$constructInject=null;如果要注入的构造参数不为空if(!empty($argInjects)){//创建__construct$的注入方法constructInject=newMethodInject('__construct',$argInjects);}//移除构造参数的定义//移除构造定义unset($definition[0]);//解析配置的__option部分//解析定义选项$option=$definition['__option']??[];if(!is_array($option)){thrownewInvalidArgumentException('__optionfordefinitionmustbearray');}//移除__option配置//移除`__option`unset($definition['__option']);//解析属性配置//解析定义属性$propertyInjects=[];//遍历所有剩余的配置foreach($definitionas$propertyName=>$propertyValue){//如果属性名不是字符串,会报错if(!is_string($propertyName)){thrownewInvalidArgumentException('定义中的属性键必须是字符串');}//获取属性值和类型[$proValue,$proIsRef]=$this->getValueByRef($propertyValue);//如果属性是数组,则重新遍历设置//解析数组的属性if(is_array($proValue)){$proValue=$this->parseArrayProperty($proValue);}//创建属性注入对象$propertyInject=newPropertyInjection($propertyName,$proValue,$proIsRef);//保存属性注入对象$propertyInjects[$propertyName]=$propertyInject;}return[$constructInject,$propertyInjects,$option];}获取参数的实际值以及是否被引用:protectedfunctiongetValueByRef($value):数组{if(!is_string($value)){return[$value,false];}//注册匹配$isRef=preg_match('/^${(.*)}$/',$value,$match);如果($isRef&&isset($match[1])){返回[$match[1],(bool)$isRef];}return[$value,false];}createnew定义对象:privatefunctioncreateObjectDefinition(string$beanName,array$definition):void{//获取配置中定义的类名,如果不存在,报错会报$className=$definition['class']??'';if(empty($className)){thrownewInvalidArgumentException(sprintf('%skeyfordefinitionmustbedefinedclass',$beanName));}//通过定义对象名(beanName)和类名来实例化一个新的定义对象$objDefinition=newObjectDefinition($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配置信息,更新上一节获取的定义对象,创建定义上一节中未创建的对象。
