spring解析element

一、解析默认命名空间的element
调用的方法为:org.springframework.beans.factory.xml.DefaultBeanDefinitionDocumentReader.parseDefaultElement(Element, BeanDefinitionParserDelegate)
执行过程为:
1 如果element的nodeName为import,调用importBeanDefinitionResource(ele)方法
(1)获取element的resource属性得到配置文件的location
(2)解析location中的Placeholders,如"${user.dir}"
(3)判断location是绝对的URI还是相对的URI
(4)不论绝对的还是相对的URL,都是调用this.readerContext.reader的loadBeanDefinitions方法完成beanDefinition的加载
2 如果element的nodeName为alias,调用processAliasRegistration(ele)方法
(1)获取element的name和alias属性
(2)getReaderContext().getRegistry().registerAlias(name, alias)
(3)getReaderContext().fireAliasRegistered(name, alias, extractSource(ele))
3 如果element的nodeName为bean,调用processBeanDefinition(ele, delegate)方法
(1)调用BeanDefinitionParserDelegate的parseBeanDefinitionElement方法:
1)先获取element的id和name属性,如果name包含",;"则以name为alias;
2)如果id为空,beanName为alias数组的第一个元素,否则为id;
3)校验beanName和aliases在当前beans element层级是否被使用过;
4)调用parseBeanDefinitionElement方法解析element并得到AbstractBeanDefinition:
a)解析element的class和parent属性,用className和parent createBeanDefinition(AbstractBeanDefinition)
b)parseBeanDefinitionAttributes:先判断element是否包含singleton属性,如果包含就报错,错误信息为"Old 1.x 'singleton' attribute in use - upgrade to 'scope' declaration";解析element的scope、abstract、lazyInit、autowire、dependency-check、depends-on、autowire-candidate、primary、init-method、destroy-method、factory-method、factory-bean属性并设置beanDefinition的相应属性。
c)用DomUtils的getChildElementValueByTagName方法获取element的description并设置beanDefinition的description属性;
d)调用parseMetaElements方法解析element的meta子元素:获取element的所有子元素,然后遍历;找到meta元素,获取其key、value属性并新建BeanMetadataAttribute,加入到beanDefinition的attribute属性中(此时的beanDefinition以BeanMetadataAttributeAccessor类型作为参数传给parseMetaElements方法)
e)调用parseLookupOverrideSubElements方法解析element的lookup-method子元素:获取element的所有子元素,然后遍历;找到lookup-method元素,获取其name、bean属性并新建LookupOverride,加入到beanDefinition的MethodOverrides属性中
f)调用parseLookupOverrideSubElements方法解析element的replaced-method子元素:先获取element的所有子元素,然后遍历;找到replaced-method元素,获取其name、replacer属性并新建ReplaceOverride,获取replaced-method元素的arg-type子元素、找到其match属性并加入到ReplaceOverride的TypeIdentifier中,最后将ReplaceOverride加入到beanDefinition的MethodOverrides属性中
g)调用parseConstructorArgElements方法解析constructor-arg子元素,获取element的所有子元素,找到constructor-arg子元素后调用parseConstructorArgElement方法:获取constructor-arg子元素的index、type、name属性,调用parsePropertyValue获取value值并新建ConstructorArgumentValues.ValueHolder,设置type和name,根据index是否为空分别加入到beanDefinition的constructorArgumentValues的indexedArgumentValues属性或genericArgumentValues属性中。其中parsePropertyValue方法参数为Element ele, BeanDefinition bd, String propertyName,执行过程如下:
新建elementName,值根据propertyName参数是否为空分别为"<property> element for property '" + propertyName + "'"、"<constructor-arg> element";通过for循环确保ele除description和meta外只包含一个子元素;判断ele是否包含ref、value属性,ref和value不能同时存在,ref或value不能与子元素同时存在;如果包含ref属性,新建RuntimeBeanReference并返回;如果包含value属性,新建TypedStringValue并返回;如果包含子元素,调用parsePropertySubElement解析子元素:
如果不是默认命名空间的调用parseNestedCustomElement方法:先调用parseCustomElement得到beanDefinition,然后返回新创建的beanDefinitionHolder;
如果nodename为bean,调用parseBeanDefinitionElement方法获取beanDefinitionHolder并返回;
如果nodename为ref,先获取ele的bean或local或parent属性作为refName,创建RuntimeBeanReference并返回;
如果nodename为idref,调用parseIdRefElement方法:先获取ele的bean或local属性作为refName,创建RuntimeBeanReference并返回;
如果nodename为value,调用parseValueElement方法:获取ele的text和type属性,调用buildTypedStringValue方法获取TypedStringValue并返回;
如果nodename为null,创建参数为null的TypedStringValue并返回;
如果nodename为array,调用parseArrayElement方法:获取ele的value-type属性;获取child节点;新建ManagedArray并作为参数调用parseCollectionElements方法,这个方法中再递归调用parsePropertySubElement方法将解析后的值加入ManagedArray中;
如果nodename为list,调用parseArrayElement方法:获取ele的value-type属性;获取child节点;新建ManagedList并作为参数调用parseCollectionElements方法,这个方法中再递归调用parsePropertySubElement方法将解析后的值加入ManagedList中;
如果nodename为set,调用parseSetElement方法:获取ele的value-type属性;获取child节点;新建ManagedSet并作为参数调用parseCollectionElements方法,这个方法中再递归调用parsePropertySubElement方法将解析后的值加入ManagedSet中;
如果nodename为map,调用parseMapElement方法:获取ele的key-type和value-type属性;获取子节点中的entry节点;新建ManagedMap;遍历所有entry节点:
确保每个entry节点除description节点和key节点外只能有一个子节点,
判断entry节点是否有key和key-ref属性,key属性、key-ref属性、key子元素不能同时存在,
如果key属性存在调用buildTypedStringValueForMap方法得到TypedStringValue对象作为key,
如果key-ref属性存在获取其值然后创建RuntimeBeanReference对象作为key,
如果key子元素存在调用parseKeyElement方法,这个方法先循环遍历key元素的子元素确保其只有一个子元素,然后递归调用parsePropertySubElement方法并将结果返回作为key,
然后判断entry节点是否有value、value-ref和value-type属性,value属性、value-ref属性和value子元素不能同时存在,value-ref属性、value-type属性和value子元素也不能同时存在,
如果value属性存在调用buildTypedStringValueForMap方法得到TypedStringValue对象作为value,
如果value-ref属性存在获取其值然后创建RuntimeBeanReference对象作为value,
如果value子元素存在递归调用parsePropertySubElement方法并将结果返回作为value,
将key和value加入到ManagedMap中
如果nodename为props,调用parsePropsElement方法:新建ManagedProperties,然后获取所有的prop子节点,遍历子节点获取其key属性和text,新建TypedStringValue类型的keyHolder、valueHolder并put到ManagedProperties中;
如果nodename不是以上,则报错。
h)调用parsePropertyElements方法解析property子元素,先获取element的子元素,然后遍历子元素,调用parsePropertyElement方法:获取property元素的name属性,然后调用parsePropertyValue方法解析property元素得到property的值,新建PropertyValue然后调用parseMetaElements解析property的子元素中的meta元素,获取meta元素的key和value属性创建BeanMetadataAttribute,然后加入到PropertyValue中(此时的PropertyValue以BeanMetadataAttributeAccessor类型作为参数传给parseMetaElements方法),最后将PropertyValue加入到beanDefinition的propertyValueList属性中;
i)调用parseQualifierElements方法解析qualifier子元素,先获取element的子元素,然后遍历子元素,调用parseQualifierElement方法:获取qualifier元素的type属性,创建AutowireCandidateQualifier对象,获取qualifier元素的value属性并设置AutowireCandidateQualifier对象的value属性值为value;获取qualifier元素的子元素,处理nodename为attribute的子元素,获取attribute子元素的key、vaule属性并新建BeanMetadataAttribute对象,添加到AutowireCandidateQualifier对象的attributes属性中;最后,将AutowireCandidateQualifier对象添加到beanDefinition的qualifiers属性中;
5)如果parseBeanDefinitionElement方法返回的beanDefinition不为空,如果beanName为空,如果containingBean不为空时,调用BeanDefinitionReaderUtils的generateBeanName方法获取beanName,如果containingBean为空,调用当前delegate的readerContext的generateBeanName方法获取beanName,如果beanDefinition包含beanClass就将beanClassName作为别名;根据beanDefinition, beanName, aliasesArray创建BeanDefinitionHolder返回。
如果parseBeanDefinitionElement方法返回的beanDefinition为空,返回null。
(2) 如果返回的beanDefinitionHolder不为空:调用delegate的decorateBeanDefinitionIfRequired方法,这个方法中先根据ele的所有属性分别调用decorateIfRequired方法,再根据所有子元素调用decorateIfRequired方法,decorateIfRequired方法获取node的namespaceUri对应的handler,然后调用handler的decorate方法完成对beanDefinition的装饰;调用BeanDefinitionReaderUtils的registerBeanDefinition方法,将修饰后的beanDefinition注册到beanFactory;
(3)调用delegate的readerContext的fireComponentRegistered方法发布registration event。
4 如果element的nodeName为beans,调用doRegisterBeanDefinitions(ele)方法(递归)

二、解析自定义命名空间的element
调用的方法为:org.springframework.beans.factory.xml.BeanDefinitionParserDelegate.parseCustomElement(Element, BeanDefinition)
执行过程为:
1 获取namespaceUri
2 调用this.readerContext的NamespaceHandlerResolver的resolve(namespaceUri)方法,根据namespaceUri获取handler。
DefaultNamespaceHandlerResolver的resolve方法,先判断this.handlerMappings是否为null,如果为null进行初始化,读取所有的META-INF/spring.handlers,将其中的handler配置解析为Properties并转为ConcurrentHashMap然后赋值给this.handlerMappings;再获取namespaceUri对应的handler的类名,实例化,执行其init方法,放入handlerMappings;返回handler。
3 调用handler的parse方法,传入参数为element和新创建的ParserContext
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值