默认标签的解析
分为四种:import,alias,bean,beans,在下面函数中进行

1 private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) { 2 if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) { 3 importBeanDefinitionResource(ele); 4 } 5 else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) { 6 processAliasRegistration(ele); 7 } 8 else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) { 9 processBeanDefinition(ele, delegate); 10 } 11 else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) { 12 // recurse 13 doRegisterBeanDefinitions(ele); 14 } 15 }
先看bean标签的解析与注册的大致过程

//BeanDefinitionParserDelegate:定义解析Element的各种方法 //BeanDefinitionHolder:Holder for a BeanDefinition with name and aliases.Can be registered as a placeholder for an inner bean. protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) { BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele); if (bdHolder != null) { bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder); try { // Register the final decorated instance. BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry()); } catch (BeanDefinitionStoreException ex) { getReaderContext().error("Failed to register bean definition with name '" + bdHolder.getBeanName() + "'", ele, ex); } // Send registration event. getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder)); } }
(1)先调用BeanDefinitionParserDelegate.parseBeanDefinitionElement(),对xml中的各种属性进行解析,方法返回BeanDefinitionHolder类型的实例bdHolder
(2)bdHolder下有自定义标签则对自定义标签进行解析
(3)对bdHolder进行注册
元素解析大致过程

1 @Nullable 2 public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) { 3 //获取id 4 String id = ele.getAttribute(ID_ATTRIBUTE); 5 //获取name 6 String nameAttr = ele.getAttribute(NAME_ATTRIBUTE); 7 8 Listaliases = new ArrayList<>(); 9 if (StringUtils.hasLength(nameAttr)) { 10 String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS); 11 aliases.addAll(Arrays.asList(nameArr)); 12 } 13 14 String beanName = id; 15 if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) { 16 beanName = aliases.remove(0); 17 if (logger.isTraceEnabled()) { 18 logger.trace("No XML 'id' specified - using '" + beanName + 19 "' as bean name and " + aliases + " as aliases"); 20 } 21 } 22 23 // 24 if (containingBean == null) { 25 checkNameUniqueness(beanName, aliases, ele); 26 } 27 28 //解析beanDefinition标签 29 AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean); 30 if (beanDefinition != null) { 31 if (!StringUtils.hasText(beanName)) { 32 try { 33 if (containingBean != null) { 34 beanName = BeanDefinitionReaderUtils.generateBeanName( 35 beanDefinition, this.readerContext.getRegistry(), true); 36 } 37 else { 38 beanName = this.readerContext.generateBeanName(beanDefinition); 39 // Register an alias for the plain bean class name, if still possible, 40 // if the generator returned the class name plus a suffix. 41 // This is expected for Spring 1.2/2.0 backwards compatibility. 42 String beanClassName = beanDefinition.getBeanClassName(); 43 if (beanClassName != null && 44 beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() && 45 !this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) { 46 aliases.add(beanClassName); 47 } 48 } 49 if (logger.isTraceEnabled()) { 50 logger.trace("Neither XML 'id' nor 'name' specified - " + 51 "using generated bean name [" + beanName + "]"); 52 } 53 } 54 catch (Exception ex) { 55 error(ex.getMessage(), ele); 56 return null; 57 } 58 } 59 String[] aliasesArray = StringUtils.toStringArray(aliases); 60 return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray); 61 } 62 63 return null; 64 }
(1)获取标签中的id,name属性,当name不为空情况下获取其aliases
(2)解析其他的属性封装在AbstractBeanDefinition中并返回实例beanDefinition
(3)当bean无id属性则按照默认规则为其生成,并校验是否添加至aliases
(4)将beanDefinition,beanName,获取的aliases的aliasesArray封装至BeanDefinitionHolder中
具体解析了哪些其他标签

1 @Nullable 2 public AbstractBeanDefinition parseBeanDefinitionElement( 3 Element ele, String beanName, @Nullable BeanDefinition containingBean) { 4 5 this.parseState.push(new BeanEntry(beanName)); 6 7 String className = null; 8 if (ele.hasAttribute(CLASS_ATTRIBUTE)) { 9 className = ele.getAttribute(CLASS_ATTRIBUTE).trim(); 10 } 11 String parent = null; 12 if (ele.hasAttribute(PARENT_ATTRIBUTE)) { 13 parent = ele.getAttribute(PARENT_ATTRIBUTE); 14 } 15 16 try { 17 //创建GenericBeanDefinition类型的实例,用于承载属性的实例 18 AbstractBeanDefinition bd = createBeanDefinition(className, parent); 19 20 //解析bean默认的各种属性 21 parseBeanDefinitionAttributes(ele, beanName, containingBean, bd); 22 bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT)); 23 24 //解析元数据 25 parseMetaElements(ele, bd); 26 //解析lookup-method方法 27 parseLookupOverrideSubElements(ele, bd.getMethodOverrides()); 28 //解析replaced-method方法 29 parseReplacedMethodSubElements(ele, bd.getMethodOverrides()); 30 31 //解析构造函数 32 parseConstructorArgElements(ele, bd); 33 //解析Property 34 parsePropertyElements(ele, bd); 35 //解析Qualifier 36 parseQualifierElements(ele, bd); 37 38 bd.setResource(this.readerContext.getResource()); 39 bd.setSource(extractSource(ele)); 40 41 return bd; 42 } 43 catch (ClassNotFoundException ex) { 44 error("Bean class [" + className + "] not found", ele, ex); 45 } 46 catch (NoClassDefFoundError err) { 47 error("Class that bean class [" + className + "] depends on not found", ele, err); 48 } 49 catch (Throwable ex) { 50 error("Unexpected failure during bean definition parsing", ele, ex); 51 } 52 finally { 53 this.parseState.pop(); 54 } 55 56 return null; 57 }
bean的各种属性

1 /** 2 * Apply the attributes of the given bean element to the given bean * definition. 3 * @param ele bean declaration element 4 * @param beanName bean name 5 * @param containingBean containing bean definition 6 * @return a bean definition initialized according to the bean element attributes 7 */ 8 public AbstractBeanDefinition parseBeanDefinitionAttributes(Element ele, String beanName, 9 @Nullable BeanDefinition containingBean, AbstractBeanDefinition bd) { 10 11 if (ele.hasAttribute(SINGLETON_ATTRIBUTE)) { 12 error("Old 1.x 'singleton' attribute in use - upgrade to 'scope' declaration", ele); 13 } 14 else if (ele.hasAttribute(SCOPE_ATTRIBUTE)) { 15 bd.setScope(ele.getAttribute(SCOPE_ATTRIBUTE)); 16 } 17 else if (containingBean != null) { 18 // Take default from containing bean in case of an inner bean definition. 19 // 如果是内部bean定义,则从包含bean中获取默认值。 20 bd.setScope(containingBean.getScope()); 21 } 22 23 if (ele.hasAttribute(ABSTRACT_ATTRIBUTE)) { 24 bd.setAbstract(TRUE_VALUE.equals(ele.getAttribute(ABSTRACT_ATTRIBUTE))); 25 } 26 27 String lazyInit = ele.getAttribute(LAZY_INIT_ATTRIBUTE); 28 if (isDefaultValue(lazyInit)) { 29 lazyInit = this.defaults.getLazyInit(); 30 } 31 bd.setLazyInit(TRUE_VALUE.equals(lazyInit)); 32 33 String autowire = ele.getAttribute(AUTOWIRE_ATTRIBUTE); 34 bd.setAutowireMode(getAutowireMode(autowire)); 35 36 if (ele.hasAttribute(DEPENDS_ON_ATTRIBUTE)) { 37 String dependsOn = ele.getAttribute(DEPENDS_ON_ATTRIBUTE); 38 bd.setDependsOn(StringUtils.tokenizeToStringArray(dependsOn, MULTI_VALUE_ATTRIBUTE_DELIMITERS)); 39 } 40 41 String autowireCandidate = ele.getAttribute(AUTOWIRE_CANDIDATE_ATTRIBUTE); 42 if (isDefaultValue(autowireCandidate)) { 43 String candidatePattern = this.defaults.getAutowireCandidates(); 44 if (candidatePattern != null) { 45 String[] patterns = StringUtils.commaDelimitedListToStringArray(candidatePattern); 46 bd.setAutowireCandidate(PatternMatchUtils.simpleMatch(patterns, beanName)); 47 } 48 } 49 else { 50 bd.setAutowireCandidate(TRUE_VALUE.equals(autowireCandidate)); 51 } 52 53 if (ele.hasAttribute(PRIMARY_ATTRIBUTE)) { 54 bd.setPrimary(TRUE_VALUE.equals(ele.getAttribute(PRIMARY_ATTRIBUTE))); 55 } 56 57 if (ele.hasAttribute(INIT_METHOD_ATTRIBUTE)) { 58 String initMethodName = ele.getAttribute(INIT_METHOD_ATTRIBUTE); 59 bd.setInitMethodName(initMethodName); 60 } 61 else if (this.defaults.getInitMethod() != null) { 62 bd.setInitMethodName(this.defaults.getInitMethod()); 63 bd.setEnforceInitMethod(false); 64 } 65 66 if (ele.hasAttribute(DESTROY_METHOD_ATTRIBUTE)) { 67 String destroyMethodName = ele.getAttribute(DESTROY_METHOD_ATTRIBUTE); 68 bd.setDestroyMethodName(destroyMethodName); 69 } 70 else if (this.defaults.getDestroyMethod() != null) { 71 bd.setDestroyMethodName(this.defaults.getDestroyMethod()); 72 bd.setEnforceDestroyMethod(false); 73 } 74 75 if (ele.hasAttribute(FACTORY_METHOD_ATTRIBUTE)) { 76 bd.setFactoryMethodName(ele.getAttribute(FACTORY_METHOD_ATTRIBUTE)); 77 } 78 if (ele.hasAttribute(FACTORY_BEAN_ATTRIBUTE)) { 79 bd.setFactoryBeanName(ele.getAttribute(FACTORY_BEAN_ATTRIBUTE)); 80 } 81 82 return bd; 83 }
具体看解析子元素meta标签

1 public void parseMetaElements(Element ele, BeanMetadataAttributeAccessor attributeAccessor) { 2 NodeList nl = ele.getChildNodes(); 3 for (int i = 0; i < nl.getLength(); i++) { 4 Node node = nl.item(i); 5 if (isCandidateElement(node) && nodeNameEquals(node, META_ELEMENT)) { 6 Element metaElement = (Element) node; 7 String key = metaElement.getAttribute(KEY_ATTRIBUTE); 8 String value = metaElement.getAttribute(VALUE_ATTRIBUTE); 9 BeanMetadataAttribute attribute = new BeanMetadataAttribute(key, value); 10 attribute.setSource(extractSource(metaElement)); 11 attributeAccessor.addMetadataAttribute(attribute); 12 } 13 } 14 }

1 <bean id="tiger" class="com.vi.springbean.Tiger"> 2 <meta key="tigerKey" value="hello"/> 3 bean>
具体看解析子元素lookup-method标签

1 public void parseLookupOverrideSubElements(Element beanEle, MethodOverrides overrides) { 2 NodeList nl = beanEle.getChildNodes(); 3 for (int i = 0; i < nl.getLength(); i++) { 4 Node node = nl.item(i); 5 if (isCandidateElement(node) && nodeNameEquals(node, LOOKUP_METHOD_ELEMENT)) { 6 Element ele = (Element) node; 7 //="" bean=""/> 8 String methodName = ele.getAttribute(NAME_ATTRIBUTE); 9 String beanRef = ele.getAttribute(BEAN_ELEMENT); 10 LookupOverride override = new LookupOverride(methodName, beanRef); 11 override.setSource(extractSource(ele)); 12 overrides.addOverride(override); 13 } 14 } 15 }
其实和meta标签解析大同小异
看一下lookup-method标签具体如何使用

1 public class Animal { 2 public void sayHello(){ 3 System.out.println("hello ··"); 4 } 5 }

1 public class Tiger extends Animal { 2 3 @Override 4 public void sayHello() { 5 System.out.println("hello 我是王者"); 6 } 7 }

1 public class Mouse extends Animal{ 2 @Override 3 public void sayHello() { 4 System.out.println("hello 我是生肖之首"); 5 } 6 }

1 public abstract class LookUpTest { 2 3 public abstract Animal getBean(); 4 5 public void say(){ 6 this.getBean().sayHello(); 7 } 8 }

1 public class Test { 2 @org.junit.Test 3 public void test() { 4 String path = "spring-config.xml"; 5 ApplicationContext bf = new ClassPathXmlApplicationContext(path); 6 LookUpTest bean = bf.getBean(LookUpTest.class); 7 bean.say(); 8 } 9 }
当xml配置如下:

1 xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xsi:schemaLocation="http://www.springframework.org/schema/beans 5 http://www.springframework.org/schema/beans/spring-beans.xsd"> 6 7 <bean id="lookUpTest" class="com.vi.springbean.LookUpTest"> 8 <lookup-method name="getBean" bean="tiger">lookup-method> 9 bean> 10 11 <bean id="mouse" class="com.vi.springbean.Mouse">bean> 12 <bean id="tiger" class="com.vi.springbean.Tiger">bean> 13 14 beans>
运行结果:
hello 我是动物之王
当xml配置如下

1 xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xsi:schemaLocation="http://www.springframework.org/schema/beans 5 http://www.springframework.org/schema/beans/spring-beans.xsd"> 6 7 <bean id="lookUpTest" class="com.vi.springbean.LookUpTest"> 8 <lookup-method name="getBean" bean="mouse">lookup-method> 9 bean> 10 11 <bean id="mouse" class="com.vi.springbean.Mouse">bean> 12 <bean id="tiger" class="com.vi.springbean.Tiger">bean> 13 14 beans>
运行结果:
hello 我是生肖之首
这个配置完成的功能就是通过更改xml中lookup-method的配置,bean对应的对象作为getBean的返回
这是一种特殊的注入方式,被称为获取器注入,他是把一个方法声明为返回某种类型的bean,但实际要返回的bean是在xml文件中配置的。
好处是看解决程序依赖
具体看解析子元素replaced-method标签

1 /** 2 * Parse replaced-method sub-elements of the given bean element. 3 */ 4 public void parseReplacedMethodSubElements(Element beanEle, MethodOverrides overrides) { 5 NodeList nl = beanEle.getChildNodes(); 6 for (int i = 0; i < nl.getLength(); i++) { 7 Node node = nl.item(i); 8 if (isCandidateElement(node) && nodeNameEquals(node, REPLACED_METHOD_ELEMENT)) { 9 Element replacedMethodEle = (Element) node; 10 //11 String name = replacedMethodEle.getAttribute(NAME_ATTRIBUTE); 12 String callback = replacedMethodEle.getAttribute(REPLACER_ATTRIBUTE); 13 ReplaceOverride replaceOverride = new ReplaceOverride(name, callback); 14 // Look for arg-type match elements. 15 List argTypeEles = DomUtils.getChildElementsByTagName(replacedMethodEle, ARG_TYPE_ELEMENT); 16 for (Element argTypeEle : argTypeEles) { 17 String match = argTypeEle.getAttribute(ARG_TYPE_MATCH_ATTRIBUTE); 18 match = (StringUtils.hasText(match) ? match : DomUtils.getTextValue(argTypeEle)); 19 if (StringUtils.hasText(match)) { 20 replaceOverride.addTypeIdentifier(match); 21 } 22 } 23 replaceOverride.setSource(extractSource(replacedMethodEle)); 24 overrides.addOverride(replaceOverride); 25 } 26 } 27 }
看一下replaced-method标签具体如何使用

1 public class Replacer { 2 public void changeMe(){ 3 System.out.println("hello please change me"); 4 } 5 }

1 public class ReplaceTest implements MethodReplacer { 2 @Override 3 public Object reimplement(Object obj, Method method, Object[] args) throws Throwable { 4 System.out.println("每个人都将成为王者"); 5 return null; 6 } 7 }

1 xml version="1.0" encoding="UTF-8"?> 2 <beans xmlns="http://www.springframework.org/schema/beans" 3 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 4 xsi:schemaLocation="http://www.springframework.org/schema/beans 5 http://www.springframework.org/schema/beans/spring-beans.xsd"> 6 7 <bean id="replacer" class="com.vi.springbean.Replacer"> 8 <replaced-method name="changeMe" replacer="replaceTest">replaced-method> 9 bean> 10 11 <bean id="replaceTest" class="com.vi.springbean.ReplaceTest">bean> 12 13 beans>

1 public class Test { 2 @org.junit.Test 3 public void test() { 4 String path = "spring-config.xml"; 5 ApplicationContext bf = new ClassPathXmlApplicationContext(path); 6 Replacer bean = bf.getBean(Replacer.class); 7 bean.changeMe(); 8 } 9 }
运行结果:
每个人都将成为王者
解析子元素constructor-arg

1 /** 2 * Parse constructor-arg sub-elements of the given bean element. 3 */ 4 public void parseConstructorArgElements(Element beanEle, BeanDefinition bd) { 5 NodeList nl = beanEle.getChildNodes(); 6 for (int i = 0; i < nl.getLength(); i++) { 7 Node node = nl.item(i); 8 if (isCandidateElement(node) && nodeNameEquals(node, CONSTRUCTOR_ARG_ELEMENT)) { 9 parseConstructorArgElement((Element) node, bd); 10 } 11 } 12 }

1 public void parseConstructorArgElement(Element ele, BeanDefinition bd) { 2 String indexAttr = ele.getAttribute(INDEX_ATTRIBUTE); 3 String typeAttr = ele.getAttribute(TYPE_ATTRIBUTE); 4 String nameAttr = ele.getAttribute(NAME_ATTRIBUTE); 5 if (StringUtils.hasLength(indexAttr)) { 6 try { 7 int index = Integer.parseInt(indexAttr); 8 if (index < 0) { 9 error("'index' cannot be lower than 0", ele); 10 } 11 else { 12 try { 13 this.parseState.push(new ConstructorArgumentEntry(index)); 14 Object value = parsePropertyValue(ele, bd, null); 15 ConstructorArgumentValues.ValueHolder valueHolder = new ConstructorArgumentValues.ValueHolder(value); 16 if (StringUtils.hasLength(typeAttr)) { 17 valueHolder.setType(typeAttr); 18 } 19 if (StringUtils.hasLength(nameAttr)) { 20 valueHolder.setName(nameAttr); 21 } 22 valueHolder.setSource(extractSource(ele)); 23 if (bd.getConstructorArgumentValues().hasIndexedArgumentValue(index)) { 24 error("Ambiguous constructor-arg entries for index " + index, ele); 25 } 26 else { 27 bd.getConstructorArgumentValues().addIndexedArgumentValue(index, valueHolder); 28 } 29 } 30 finally { 31 this.parseState.pop(); 32 } 33 } 34 } 35 catch (NumberFormatException ex) { 36 error("Attribute 'index' of tag 'constructor-arg' must be an integer", ele); 37 } 38 } 39 else { 40 try { 41 this.parseState.push(new ConstructorArgumentEntry()); 42 Object value = parsePropertyValue(ele, bd, null); 43 ConstructorArgumentValues.ValueHolder valueHolder = new ConstructorArgumentValues.ValueHolder(value); 44 if (StringUtils.hasLength(typeAttr)) { 45 valueHolder.setType(typeAttr); 46 } 47 if (StringUtils.hasLength(nameAttr)) { 48 valueHolder.setName(nameAttr); 49 } 50 valueHolder.setSource(extractSource(ele)); 51 bd.getConstructorArgumentValues().addGenericArgumentValue(valueHolder); 52 } 53 finally { 54 this.parseState.pop(); 55 } 56 } 57 }
当配置中指定了index属性
(1)获取index值,且检验index值不能小于0,且需未integer类型
(2)获取value,type,name值,并封装在ConstructorArgumentValues.ValueHolder的实例valueHolder中
(3)不能重复指定相同index属性下的值
(4)以index,valueHolder(key,value)的形式添加到当前的BeanDefinition的ConstructorArgumentValues的indexedArgumentValues(是一个map)中
当配置中未指定index属性
(1) 获取value,type,name值,并封装在ConstructorArgumentValues.ValueHolder的实例valueHolder中
(2)添加至ConstructorArgumentValues的genericArgumentValues中
可见根据有无index属在最终存储位置,形式不一样
1 private final MapindexedArgumentValues = new LinkedHashMap<>(); 2 3 private final List genericArgumentValues = new ArrayList<>();
parsePropertyValue方法

1 /** 2 * Get the value of a property element. May be a list etc. 3 * Also used for constructor arguments, "propertyName" being null in this case. 4 */ 5 @Nullable 6 public Object parsePropertyValue(Element ele, BeanDefinition bd, @Nullable String propertyName) { 7 String elementName = (propertyName != null ? 8 "element for property '" + propertyName + "'" : 9 " element"); 10 11 // Should only have one child element: ref, value, list, etc. 12 NodeList nl = ele.getChildNodes(); 13 Element subElement = null; 14 for (int i = 0; i < nl.getLength(); i++) { 15 Node node = nl.item(i); 16 // 对于description,meta属性不做处理 17 if (node instanceof Element && !nodeNameEquals(node, DESCRIPTION_ELEMENT) && 18 !nodeNameEquals(node, META_ELEMENT)) { 19 // Child element is what we're looking for. 20 if (subElement != null) { 21 error(elementName + " must not contain more than one sub-element", ele); 22 } 23 else { 24 subElement = (Element) node; 25 } 26 } 27 } 28 29 boolean hasRefAttribute = ele.hasAttribute(REF_ATTRIBUTE); 30 boolean hasValueAttribute = ele.hasAttribute(VALUE_ATTRIBUTE); 31 // ref,value属性不能同时存在,且都不能有子元素 32 if ((hasRefAttribute && hasValueAttribute) || 33 ((hasRefAttribute || hasValueAttribute) && subElement != null)) { 34 error(elementName + 35 " is only allowed to contain either 'ref' attribute OR 'value' attribute OR sub-element", ele); 36 } 37 38 if (hasRefAttribute) { 39 String refName = ele.getAttribute(REF_ATTRIBUTE); 40 if (!StringUtils.hasText(refName)) { 41 error(elementName + " contains empty 'ref' attribute", ele); 42 } 43 RuntimeBeanReference ref = new RuntimeBeanReference(refName); 44 ref.setSource(extractSource(ele)); 45 return ref; 46 } 47 else if (hasValueAttribute) { 48 TypedStringValue valueHolder = new TypedStringValue(ele.getAttribute(VALUE_ATTRIBUTE)); 49 valueHolder.setSource(extractSource(ele)); 50 return valueHolder; 51 } 52 else if (subElement != null) { 53 return parsePropertySubElement(subElement, bd); 54 } 55 else { 56 // Neither child element nor "ref" or "value" attribute found. 57 error(elementName + " must specify a ref or value", ele); 58 return null; 59 } 60 }
(1)对于构造函数中子元素的解析是跳过meta,description属性
(2)ref,value属性不能同时存在,且ref,value都不能有子元素
(3)或解析ref标签,封装至RuntimeBeanReference中
(4)或解析value标签,封装至TypedStringValue中
(5)或解析子元素便签(接下来看这个是怎么实现的)
解析子元素便签

1 /** 2 * Parse a value, ref or collection sub-element of a property or 3 * constructor-arg element. 4 * @param ele subelement of property element; we don't know which yet 5 * @param bd the current bean definition (if any) 6 */ 7 @Nullable 8 public Object parsePropertySubElement(Element ele, @Nullable BeanDefinition bd) { 9 return parsePropertySubElement(ele, bd, null); 10 }

1 /** 2 * Parse a value, ref or collection sub-element of a property or 3 * constructor-arg element. 4 * @param ele subelement of property element; we don't know which yet 5 * @param bd the current bean definition (if any) 6 * @param defaultValueType the default type (class name) for any 7 * {@code} tag that might be created 8 */ 9 @Nullable 10 public Object parsePropertySubElement(Element ele, @Nullable BeanDefinition bd, @Nullable String defaultValueType) { 11 if (!isDefaultNamespace(ele)) { 12 return parseNestedCustomElement(ele, bd); 13 } 14 else if (nodeNameEquals(ele, BEAN_ELEMENT)) { 15 BeanDefinitionHolder nestedBd = parseBeanDefinitionElement(ele, bd); 16 if (nestedBd != null) { 17 nestedBd = decorateBeanDefinitionIfRequired(ele, nestedBd, bd); 18 } 19 return nestedBd; 20 } 21 else if (nodeNameEquals(ele, REF_ELEMENT)) { 22 // A generic reference to any name of any bean. 23 String refName = ele.getAttribute(BEAN_REF_ATTRIBUTE); 24 boolean toParent = false; 25 if (!StringUtils.hasLength(refName)) { 26 // A reference to the id of another bean in a parent context. 27 refName = ele.getAttribute(PARENT_REF_ATTRIBUTE); 28 toParent = true; 29 if (!StringUtils.hasLength(refName)) { 30 error("'bean' or 'parent' is required for element", ele); 31 return null; 32 } 33 } 34 if (!StringUtils.hasText(refName)) { 35 error(" element contains empty target attribute", ele); 36 return null; 37 } 38 RuntimeBeanReference ref = new RuntimeBeanReference(refName, toParent); 39 ref.setSource(extractSource(ele)); 40 return ref; 41 } 42 else if (nodeNameEquals(ele, IDREF_ELEMENT)) { 43 return parseIdRefElement(ele); 44 } 45 else if (nodeNameEquals(ele, VALUE_ELEMENT)) { 46 return parseValueElement(ele, defaultValueType); 47 } 48 else if (nodeNameEquals(ele, NULL_ELEMENT)) { 49 // It's a distinguished null value. Let's wrap it in a TypedStringValue 50 // object in order to preserve the source location. 51 TypedStringValue nullHolder = new TypedStringValue(null); 52 nullHolder.setSource(extractSource(ele)); 53 return nullHolder; 54 } 55 else if (nodeNameEquals(ele, ARRAY_ELEMENT)) { 56 return parseArrayElement(ele, bd); 57 } 58 else if (nodeNameEquals(ele, LIST_ELEMENT)) { 59 return parseListElement(ele, bd); 60 } 61 else if (nodeNameEquals(ele, SET_ELEMENT)) { 62 return parseSetElement(ele, bd); 63 } 64 else if (nodeNameEquals(ele, MAP_ELEMENT)) { 65 return parseMapElement(ele, bd); 66 } 67 else if (nodeNameEquals(ele, PROPS_ELEMENT)) { 68 return parsePropsElement(ele); 69 } 70 else { 71 error("Unknown property sub-element: [" + ele.getNodeName() + "]", ele); 72 return null; 73 } 74 }
子元素map标签解析(TODO)

1 /** 2 * Parse a map element. 3 */ 4 public Map
解析子元素property

1 * Parse property sub-elements of the given bean element. 2 */ 3 public void parsePropertyElements(Element beanEle, BeanDefinition bd) { 4 NodeList nl = beanEle.getChildNodes(); 5 for (int i = 0; i < nl.getLength(); i++) { 6 Node node = nl.item(i); 7 if (isCandidateElement(node) && nodeNameEquals(node, PROPERTY_ELEMENT)) { 8 parsePropertyElement((Element) node, bd); 9 } 10 } 11 }

1 /** 2 * Parse a property element. 3 */ 4 public void parsePropertyElement(Element ele, BeanDefinition bd) { 5 String propertyName = ele.getAttribute(NAME_ATTRIBUTE); 6 if (!StringUtils.hasLength(propertyName)) { 7 error("Tag 'property' must have a 'name' attribute", ele); 8 return; 9 } 10 this.parseState.push(new PropertyEntry(propertyName)); 11 try { 12 if (bd.getPropertyValues().contains(propertyName)) { 13 error("Multiple 'property' definitions for property '" + propertyName + "'", ele); 14 return; 15 } 16 Object val = parsePropertyValue(ele, bd, propertyName); 17 PropertyValue pv = new PropertyValue(propertyName, val); 18 parseMetaElements(ele, pv); 19 pv.setSource(extractSource(ele)); 20 bd.getPropertyValues().addPropertyValue(pv); 21 } 22 finally { 23 this.parseState.pop(); 24 } 25 }
注:
GenericBeanDefinition,ChildBeanDefinition,RootBeanDefinition 都继承AbstractBeanDefinition
AbstractBeanDefinition 继承 BeanMetadataAttributeAccessor 实现 BeanDefinition
------------------------------------------------------------------------------------------------------------------------------
------------------------------------------------------------------------------------------------------------------------------
解析默认标签中的自定义标签元素

1 /** 2 * Decorate the given bean definition through a namespace handler, if applicable. 3 * @param ele the current element 4 * @param originalDef the current bean definition 5 * @return the decorated bean definition 6 */ 7 public BeanDefinitionHolder decorateBeanDefinitionIfRequired(Element ele, BeanDefinitionHolder originalDef) { 8 return decorateBeanDefinitionIfRequired(ele, originalDef, null); 9 }

1 /** 2 * Decorate the given bean definition through a namespace handler, if applicable. 3 * @param ele the current element 4 * @param originalDef the current bean definition 5 * @param containingBd the containing bean definition (if any) 6 * @return the decorated bean definition 7 */ 8 public BeanDefinitionHolder decorateBeanDefinitionIfRequired( 9 Element ele, BeanDefinitionHolder originalDef, @Nullable BeanDefinition containingBd) { 10 11 BeanDefinitionHolder finalDefinition = originalDef; 12 13 // Decorate based on custom attributes first. 14 NamedNodeMap attributes = ele.getAttributes(); 15 for (int i = 0; i < attributes.getLength(); i++) { 16 Node node = attributes.item(i); 17 finalDefinition = decorateIfRequired(node, finalDefinition, containingBd); 18 } 19 20 // Decorate based on custom nested elements. 21 NodeList children = ele.getChildNodes(); 22 for (int i = 0; i < children.getLength(); i++) { 23 Node node = children.item(i); 24 if (node.getNodeType() == Node.ELEMENT_NODE) { 25 finalDefinition = decorateIfRequired(node, finalDefinition, containingBd); 26 } 27 } 28 return finalDefinition; 29 }
(1)对所有的我属性
(2)对于所有的子节点

1 /** 2 * Decorate the given bean definition through a namespace handler, 3 * if applicable. 4 * @param node the current child node 5 * @param originalDef the current bean definition 6 * @param containingBd the containing bean definition (if any) 7 * @return the decorated bean definition 8 */ 9 public BeanDefinitionHolder decorateIfRequired( 10 Node node, BeanDefinitionHolder originalDef, @Nullable BeanDefinition containingBd) { 11 12 String namespaceUri = getNamespaceURI(node); 13 if (namespaceUri != null && !isDefaultNamespace(namespaceUri)) { 14 NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri); 15 if (handler != null) { 16 BeanDefinitionHolder decorated = 17 handler.decorate(node, originalDef, new ParserContext(this.readerContext, this, containingBd)); 18 if (decorated != null) { 19 return decorated; 20 } 21 } 22 else if (namespaceUri.startsWith("http://www.springframework.org/")) { 23 error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", node); 24 } 25 else { 26 // A custom namespace, not to be handled by Spring - maybe "xml:...". 27 if (logger.isDebugEnabled()) { 28 logger.debug("No Spring NamespaceHandler found for XML schema namespace [" + namespaceUri + "]"); 29 } 30 } 31 } 32 return originalDef; 33 }
(1)可以看出是根据命名空间判断是否适用于自定义标签的解析条件的
注册已解析的BeanDefinition

1 /** 2 * Register the given bean definition with the given bean factory. 3 * @param definitionHolder the bean definition including name and aliases 4 * @param registry the bean factory to register with 5 * @throws BeanDefinitionStoreException if registration failed 6 */ 7 public static void registerBeanDefinition( 8 BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry) 9 throws BeanDefinitionStoreException { 10 11 // Register bean definition under primary name. 12 String beanName = definitionHolder.getBeanName(); 13 registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition()); 14 15 // Register aliases for bean name, if any. 16 String[] aliases = definitionHolder.getAliases(); 17 if (aliases != null) { 18 for (String alias : aliases) { 19 registry.registerAlias(beanName, alias); 20 } 21 } 22 }
(1)通过beanName注册
(2)通过别名注册
了解alias标签的解析
TODO
了解import标签的解析
TODO
了解beans标签的解析
递归调用beans标签的解析过程
已经是2020年的第二天了 时间过的很快 或许只有我一人觉得19年自己碌碌无为 20年加油吧