From 8e592483d1d925322d197f2efc43f4ada2a1eecd Mon Sep 17 00:00:00 2001 From: huifer Date: Mon, 28 Sep 2020 12:34:33 +0800 Subject: [PATCH] doc: --- .../Spring-BeanDefinitionParserDelegate.md | 2036 +++++++++++------ 1 file changed, 1325 insertions(+), 711 deletions(-) diff --git a/docs/Spring/clazz/Spring-BeanDefinitionParserDelegate.md b/docs/Spring/clazz/Spring-BeanDefinitionParserDelegate.md index b711509..ed229ec 100644 --- a/docs/Spring/clazz/Spring-BeanDefinitionParserDelegate.md +++ b/docs/Spring/clazz/Spring-BeanDefinitionParserDelegate.md @@ -1,859 +1,1473 @@ -# Spring-BeanDefinitionParserDelegate - +# Spring BeanDefinitionParserDelegate - Author: [HuiFer](https://github.com/huifer) -- 源码路径: `org.springframework.beans.factory.xml.BeanDefinitionParserDelegate` -- 注意: 贴出的代码为当前类(`BeanDefinitionParserDelegate`)没有将其他的调用代码贴出,详细请看[huifer-srping](https://github.com/huifer/spring-framework). -- 该类的作用是将标签解析 +- 源码阅读仓库: [SourceHot-spring](https://github.com/SourceHot/spring-framework-read) + +- 全路径`org.springframework.beans.factory.xml.BeanDefinitionParserDelegate` +- 解析 xml 中标签的委托类 + -- 下面这段代码是这个类的入口 + +- 在这个类中定义常量如下,为后续解析提供帮助 ```java - @Nullable - public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) { - // 获取id 属性 - String id = ele.getAttribute(ID_ATTRIBUTE); - // 获取 name 属性 - String nameAttr = ele.getAttribute(NAME_ATTRIBUTE); - - // 别名列表 - List aliases = new ArrayList<>(); - if (StringUtils.hasLength(nameAttr)) { - String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS); - aliases.addAll(Arrays.asList(nameArr)); - } - - // beanName = 中id的属性值 - String beanName = id; - if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) { - beanName = aliases.remove(0); - if (logger.isTraceEnabled()) { - logger.trace("No XML 'id' specified - using '" + beanName + - "' as bean name and " + aliases + " as aliases"); - } - } - - if (containingBean == null) { - checkNameUniqueness(beanName, aliases, ele); - } - - // 创建对象 - AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean); - if (beanDefinition != null) { - if (!StringUtils.hasText(beanName)) { - try { - if (containingBean != null) { - beanName = BeanDefinitionReaderUtils.generateBeanName( - beanDefinition, this.readerContext.getRegistry(), true); - } - else { - beanName = this.readerContext.generateBeanName(beanDefinition); - // Register an alias for the plain bean class name, if still possible, - // if the generator returned the class name plus a suffix. - // This is expected for Spring 1.2/2.0 backwards compatibility. - String beanClassName = beanDefinition.getBeanClassName(); - if (beanClassName != null && - beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() && - !this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) { - aliases.add(beanClassName); - } - } - if (logger.isTraceEnabled()) { - logger.trace("Neither XML 'id' nor 'name' specified - " + - "using generated bean name [" + beanName + "]"); - } - } - catch (Exception ex) { - error(ex.getMessage(), ele); - return null; - } - } - String[] aliasesArray = StringUtils.toStringArray(aliases); - return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray); - } + public static final String BEANS_NAMESPACE_URI = "http://www.springframework.org/schema/beans"; - return null; - } -``` + public static final String MULTI_VALUE_ATTRIBUTE_DELIMITERS = ",; "; -![image-20191231142829639](/image/spring/image-20191231142829639.png) + public static final String TRUE_VALUE = "true"; -该类大量的`parseXXX`开头的代码,这些方法都是对标签进行解析转换成具体的实体 + public static final String FALSE_VALUE = "false"; -### 测试用例 + public static final String DEFAULT_VALUE = "default"; -```xml - - - - + public static final String DESCRIPTION_ELEMENT = "description"; + + public static final String AUTOWIRE_NO_VALUE = "no"; + + public static final String AUTOWIRE_BY_NAME_VALUE = "byName"; + + public static final String AUTOWIRE_BY_TYPE_VALUE = "byType"; + + public static final String AUTOWIRE_CONSTRUCTOR_VALUE = "constructor"; + + public static final String AUTOWIRE_AUTODETECT_VALUE = "autodetect"; + + public static final String NAME_ATTRIBUTE = "name"; + + public static final String BEAN_ELEMENT = "bean"; + + public static final String META_ELEMENT = "meta"; + + public static final String ID_ATTRIBUTE = "id"; + + public static final String PARENT_ATTRIBUTE = "parent"; + + public static final String CLASS_ATTRIBUTE = "class"; + + public static final String ABSTRACT_ATTRIBUTE = "abstract"; + + public static final String SCOPE_ATTRIBUTE = "scope"; + + public static final String LAZY_INIT_ATTRIBUTE = "lazy-init"; + + public static final String AUTOWIRE_ATTRIBUTE = "autowire"; + + public static final String AUTOWIRE_CANDIDATE_ATTRIBUTE = "autowire-candidate"; + + public static final String PRIMARY_ATTRIBUTE = "primary"; + + public static final String DEPENDS_ON_ATTRIBUTE = "depends-on"; + + public static final String INIT_METHOD_ATTRIBUTE = "init-method"; + + public static final String DESTROY_METHOD_ATTRIBUTE = "destroy-method"; + + public static final String FACTORY_METHOD_ATTRIBUTE = "factory-method"; + + public static final String FACTORY_BEAN_ATTRIBUTE = "factory-bean"; + + public static final String CONSTRUCTOR_ARG_ELEMENT = "constructor-arg"; + + public static final String INDEX_ATTRIBUTE = "index"; + + public static final String TYPE_ATTRIBUTE = "type"; + + public static final String VALUE_TYPE_ATTRIBUTE = "value-type"; + + public static final String KEY_TYPE_ATTRIBUTE = "key-type"; + + public static final String PROPERTY_ELEMENT = "property"; + + public static final String REF_ATTRIBUTE = "ref"; + + public static final String VALUE_ATTRIBUTE = "value"; + + public static final String LOOKUP_METHOD_ELEMENT = "lookup-method"; + + public static final String REPLACED_METHOD_ELEMENT = "replaced-method"; + + public static final String REPLACER_ATTRIBUTE = "replacer"; + + public static final String ARG_TYPE_ELEMENT = "arg-type"; + + public static final String ARG_TYPE_MATCH_ATTRIBUTE = "match"; + + public static final String REF_ELEMENT = "ref"; + public static final String IDREF_ELEMENT = "idref"; + + public static final String BEAN_REF_ATTRIBUTE = "bean"; + + public static final String PARENT_REF_ATTRIBUTE = "parent"; + + public static final String VALUE_ELEMENT = "value"; + + public static final String NULL_ELEMENT = "null"; + + public static final String ARRAY_ELEMENT = "array"; + + public static final String LIST_ELEMENT = "list"; + + public static final String SET_ELEMENT = "set"; + + public static final String MAP_ELEMENT = "map"; + + public static final String ENTRY_ELEMENT = "entry"; + + public static final String KEY_ELEMENT = "key"; + + public static final String KEY_ATTRIBUTE = "key"; + + public static final String KEY_REF_ATTRIBUTE = "key-ref"; + + public static final String VALUE_REF_ATTRIBUTE = "value-ref"; + + public static final String PROPS_ELEMENT = "props"; + + public static final String PROP_ELEMENT = "prop"; + + public static final String MERGE_ATTRIBUTE = "merge"; + + public static final String QUALIFIER_ELEMENT = "qualifier"; + + public static final String QUALIFIER_ATTRIBUTE_ELEMENT = "attribute"; + + public static final String DEFAULT_LAZY_INIT_ATTRIBUTE = "default-lazy-init"; + + public static final String DEFAULT_MERGE_ATTRIBUTE = "default-merge"; + + public static final String DEFAULT_AUTOWIRE_ATTRIBUTE = "default-autowire"; + + public static final String DEFAULT_AUTOWIRE_CANDIDATES_ATTRIBUTE = "default-autowire-candidates"; + + public static final String DEFAULT_INIT_METHOD_ATTRIBUTE = "default-init-method"; + + public static final String DEFAULT_DESTROY_METHOD_ATTRIBUTE = "default-destroy-method"; + + private static final String SINGLETON_ATTRIBUTE = "singleton"; ``` -## parseBeanDefinitionAttributes -- 解析属性`scope`,`abstract`,`lazy-init` + + + + + +## populateDefaults + +- `org.springframework.beans.factory.xml.BeanDefinitionParserDelegate#populateDefaults`方法解析属性赋值给`DocumentDefaultsDefinition`对象 + + + +- 代码逻辑如下 + 1. 读取属性 + 2. 判断是否默认值 + 3. 判断是否存在属性 + 4. 赋值 ```java -public AbstractBeanDefinition parseBeanDefinitionAttributes(Element ele, String beanName, - @Nullable BeanDefinition containingBean, AbstractBeanDefinition bd) { - - if (ele.hasAttribute(SINGLETON_ATTRIBUTE)) { - error("Old 1.x 'singleton' attribute in use - upgrade to 'scope' declaration", ele); - } - else if (ele.hasAttribute(SCOPE_ATTRIBUTE)) { - bd.setScope(ele.getAttribute(SCOPE_ATTRIBUTE)); - } - else if (containingBean != null) { - // Take default from containing bean in case of an inner bean definition. - bd.setScope(containingBean.getScope()); - } - - if (ele.hasAttribute(ABSTRACT_ATTRIBUTE)) { - bd.setAbstract(TRUE_VALUE.equals(ele.getAttribute(ABSTRACT_ATTRIBUTE))); - } - - String lazyInit = ele.getAttribute(LAZY_INIT_ATTRIBUTE); - if (isDefaultValue(lazyInit)) { - lazyInit = this.defaults.getLazyInit(); - } - bd.setLazyInit(TRUE_VALUE.equals(lazyInit)); - - String autowire = ele.getAttribute(AUTOWIRE_ATTRIBUTE); - bd.setAutowireMode(getAutowireMode(autowire)); - - if (ele.hasAttribute(DEPENDS_ON_ATTRIBUTE)) { - String dependsOn = ele.getAttribute(DEPENDS_ON_ATTRIBUTE); - bd.setDependsOn(StringUtils.tokenizeToStringArray(dependsOn, MULTI_VALUE_ATTRIBUTE_DELIMITERS)); - } - - String autowireCandidate = ele.getAttribute(AUTOWIRE_CANDIDATE_ATTRIBUTE); - if (isDefaultValue(autowireCandidate)) { - String candidatePattern = this.defaults.getAutowireCandidates(); - if (candidatePattern != null) { - String[] patterns = StringUtils.commaDelimitedListToStringArray(candidatePattern); - bd.setAutowireCandidate(PatternMatchUtils.simpleMatch(patterns, beanName)); - } - } - else { - bd.setAutowireCandidate(TRUE_VALUE.equals(autowireCandidate)); - } +protected void populateDefaults(DocumentDefaultsDefinition defaults, @Nullable DocumentDefaultsDefinition parentDefaults, Element root) { + // 获取 default-lazy-init 属性值 + String lazyInit = root.getAttribute(DEFAULT_LAZY_INIT_ATTRIBUTE); + // 判断是否是默认值 + if (isDefaultValue(lazyInit)) { + // Potentially inherited from outer sections, otherwise falling back to false. + lazyInit = (parentDefaults != null ? parentDefaults.getLazyInit() : FALSE_VALUE); + } + defaults.setLazyInit(lazyInit); + + String merge = root.getAttribute(DEFAULT_MERGE_ATTRIBUTE); + if (isDefaultValue(merge)) { + // Potentially inherited from outer sections, otherwise falling back to false. + merge = (parentDefaults != null ? parentDefaults.getMerge() : FALSE_VALUE); + } + defaults.setMerge(merge); + + String autowire = root.getAttribute(DEFAULT_AUTOWIRE_ATTRIBUTE); + if (isDefaultValue(autowire)) { + // Potentially inherited from outer sections, otherwise falling back to 'no'. + autowire = (parentDefaults != null ? parentDefaults.getAutowire() : AUTOWIRE_NO_VALUE); + } + defaults.setAutowire(autowire); + + if (root.hasAttribute(DEFAULT_AUTOWIRE_CANDIDATES_ATTRIBUTE)) { + defaults.setAutowireCandidates(root.getAttribute(DEFAULT_AUTOWIRE_CANDIDATES_ATTRIBUTE)); + } + else if (parentDefaults != null) { + defaults.setAutowireCandidates(parentDefaults.getAutowireCandidates()); + } + + if (root.hasAttribute(DEFAULT_INIT_METHOD_ATTRIBUTE)) { + defaults.setInitMethod(root.getAttribute(DEFAULT_INIT_METHOD_ATTRIBUTE)); + } + else if (parentDefaults != null) { + defaults.setInitMethod(parentDefaults.getInitMethod()); + } + + if (root.hasAttribute(DEFAULT_DESTROY_METHOD_ATTRIBUTE)) { + defaults.setDestroyMethod(root.getAttribute(DEFAULT_DESTROY_METHOD_ATTRIBUTE)); + } + else if (parentDefaults != null) { + defaults.setDestroyMethod(parentDefaults.getDestroyMethod()); + } + + defaults.setSource(this.readerContext.extractSource(root)); +} +``` - if (ele.hasAttribute(PRIMARY_ATTRIBUTE)) { - bd.setPrimary(TRUE_VALUE.equals(ele.getAttribute(PRIMARY_ATTRIBUTE))); - } - if (ele.hasAttribute(INIT_METHOD_ATTRIBUTE)) { - String initMethodName = ele.getAttribute(INIT_METHOD_ATTRIBUTE); - bd.setInitMethodName(initMethodName); - } - else if (this.defaults.getInitMethod() != null) { - bd.setInitMethodName(this.defaults.getInitMethod()); - bd.setEnforceInitMethod(false); - } - if (ele.hasAttribute(DESTROY_METHOD_ATTRIBUTE)) { - String destroyMethodName = ele.getAttribute(DESTROY_METHOD_ATTRIBUTE); - bd.setDestroyMethodName(destroyMethodName); - } - else if (this.defaults.getDestroyMethod() != null) { - bd.setDestroyMethodName(this.defaults.getDestroyMethod()); - bd.setEnforceDestroyMethod(false); - } +### DocumentDefaultsDefinition - if (ele.hasAttribute(FACTORY_METHOD_ATTRIBUTE)) { - bd.setFactoryMethodName(ele.getAttribute(FACTORY_METHOD_ATTRIBUTE)); - } - if (ele.hasAttribute(FACTORY_BEAN_ATTRIBUTE)) { - bd.setFactoryBeanName(ele.getAttribute(FACTORY_BEAN_ATTRIBUTE)); - } +- 全路径:`org.springframework.beans.factory.xml.DocumentDefaultsDefinition` +- 下面放出类的属性标记 - return bd; - } +```java +public class DocumentDefaultsDefinition implements DefaultsDefinition { + + /** + * true or false + */ + @Nullable + private String lazyInit; + + /** + * true or false + */ + @Nullable + private String merge; + + /** + * no or byName or byType + */ + @Nullable + private String autowire; + + /** + * default-autowire-candidates 属性值 + */ + @Nullable + private String autowireCandidates; + + /** + * 实例化方法 + */ + @Nullable + private String initMethod; + + /** + * 摧毁方法 + */ + @Nullable + private String destroyMethod; + + @Nullable + private Object source; +} ``` -![image-20191231162505748](/image/spring/image-20191231162505748.png) -其他的标签也同样的方式**`getAttribute`**获取 -思路: -1. 判断是否有这个标签 - 1. 有直接获取,设置值 - 2. 没有跳过 -## parseMetaElements + + +## checkNameUniqueness + +- `org.springframework.beans.factory.xml.BeanDefinitionParserDelegate#checkNameUniqueness` + +- 判断 beanName 是否被使用, bean 别名是否被使用 ```java - /** - * 解析Meta 元素 - * {@code } => {@link BeanMetadataAttribute} - * Parse the meta elements underneath the given element, if any. - */ - public void parseMetaElements(Element ele, BeanMetadataAttributeAccessor attributeAccessor) { - NodeList nl = ele.getChildNodes(); - for (int i = 0; i < nl.getLength(); i++) { - Node node = nl.item(i); - if (isCandidateElement(node) && nodeNameEquals(node, META_ELEMENT)) { - Element metaElement = (Element) node; - // 获取 key 属性值 - String key = metaElement.getAttribute(KEY_ATTRIBUTE); - // 获取 value 属性值 - String value = metaElement.getAttribute(VALUE_ATTRIBUTE); - BeanMetadataAttribute attribute = new BeanMetadataAttribute(key, value); - attribute.setSource(extractSource(metaElement)); - attributeAccessor.addMetadataAttribute(attribute); - } - } - } +/** + * Validate that the specified bean name and aliases have not been used already + * within the current level of beans element nesting. + * + * 判断 beanName 是否被使用, bean 别名是否被使用 + */ +protected void checkNameUniqueness(String beanName, List aliases, Element beanElement) { + // 当前寻找的name + String foundName = null; + + // 是否有 beanName + // 使用过的name中是否存在 + if (StringUtils.hasText(beanName) && this.usedNames.contains(beanName)) { + foundName = beanName; + } + if (foundName == null) { + // 寻找匹配的第一个 + foundName = CollectionUtils.findFirstMatch(this.usedNames, aliases); + } + // 抛出异常 + if (foundName != null) { + error("Bean name '" + foundName + "' is already used in this element", beanElement); + } + + // 加入使用队列 + this.usedNames.add(beanName); + this.usedNames.addAll(aliases); +} +``` + + + + + +## createBeanDefinition + +- `org.springframework.beans.factory.support.BeanDefinitionReaderUtils#createBeanDefinition` +- 创建具有基本信息的**BeanDefinition** + 1. parent bean name + 2. bean clsss + 3. bean class name +```java +public static AbstractBeanDefinition createBeanDefinition( + @Nullable String parentName, @Nullable String className, @Nullable ClassLoader classLoader) throws ClassNotFoundException { + + GenericBeanDefinition bd = new GenericBeanDefinition(); + // 设置 父bean + bd.setParentName(parentName); + if (className != null) { + if (classLoader != null) { + // 设置 class + // 内部是通过反射创建 class + bd.setBeanClass(ClassUtils.forName(className, classLoader)); + } + else { + // 设置 class name + bd.setBeanClassName(className); + } + } + return bd; +} ``` -![image-20191231164622063](/image/spring/image-20191231164622063.png) -## parseLookupOverrideSubElements + + + +## parseBeanDefinitionElement + +- `org.springframework.beans.factory.xml.BeanDefinitionParserDelegate#parseBeanDefinitionElement(org.w3c.dom.Element, org.springframework.beans.factory.config.BeanDefinition)` +- 该方法用来解析 `` 标签信息 + + + + + + + +## + +- `org.springframework.beans.factory.xml.BeanDefinitionParserDelegate#parseBeanDefinitionElement(org.w3c.dom.Element, java.lang.String, org.springframework.beans.factory.config.BeanDefinition)` + + + + ```java - /** - * 解析{@code } - * Parse lookup-override sub-elements of the given bean element. - */ - public void parseLookupOverrideSubElements(Element beanEle, MethodOverrides overrides) { - NodeList nl = beanEle.getChildNodes(); - for (int i = 0; i < nl.getLength(); i++) { - Node node = nl.item(i); - if (isCandidateElement(node) && nodeNameEquals(node, LOOKUP_METHOD_ELEMENT)) { - Element ele = (Element) node; - String methodName = ele.getAttribute(NAME_ATTRIBUTE); - String beanRef = ele.getAttribute(BEAN_ELEMENT); - // 转换成JAVA对象 - LookupOverride override = new LookupOverride(methodName, beanRef); - override.setSource(extractSource(ele)); - overrides.addOverride(override); - } - } - } +@Nullable +public AbstractBeanDefinition parseBeanDefinitionElement( + Element ele, String beanName, @Nullable BeanDefinition containingBean) { + + this.parseState.push(new BeanEntry(beanName)); + + String className = null; + // 是否包含属性 class + if (ele.hasAttribute(CLASS_ATTRIBUTE)) { + className = ele.getAttribute(CLASS_ATTRIBUTE).trim(); + } + String parent = null; + // 是否包含属性 parent + if (ele.hasAttribute(PARENT_ATTRIBUTE)) { + parent = ele.getAttribute(PARENT_ATTRIBUTE); + } + + try { + // 创建 bean definition + AbstractBeanDefinition bd = createBeanDefinition(className, parent); + + // bean definition 属性设置 + parseBeanDefinitionAttributes(ele, beanName, containingBean, bd); + bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT)); + // 元信息设置 + parseMetaElements(ele, bd); + // lookup-override 标签解析 + parseLookupOverrideSubElements(ele, bd.getMethodOverrides()); + // replaced-method sub-elements 标签解析 + parseReplacedMethodSubElements(ele, bd.getMethodOverrides()); + + // constructor arg 标签解析 + parseConstructorArgElements(ele, bd); + // property 标签解析 + parsePropertyElements(ele, bd); + // qualifier 标签解析 + parseQualifierElements(ele, bd); + // 资源设置 + bd.setResource(this.readerContext.getResource()); + // source 设置 + bd.setSource(extractSource(ele)); + + return bd; + } + catch (ClassNotFoundException ex) { + error("Bean class [" + className + "] not found", ele, ex); + } + catch (NoClassDefFoundError err) { + error("Class that bean class [" + className + "] depends on not found", ele, err); + } + catch (Throwable ex) { + error("Unexpected failure during bean definition parsing", ele, ex); + } + finally { + this.parseState.pop(); + } + + return null; +} +``` + +### parseBeanDefinitionAttributes + +- `org.springframework.beans.factory.xml.BeanDefinitionParserDelegate#parseBeanDefinitionAttributes` + + + +- 将 xml 标签的数据读取到内存中设置给`AbstractBeanDefinition` + + +```JAVA +public AbstractBeanDefinition parseBeanDefinitionAttributes(Element ele, String beanName, + @Nullable BeanDefinition containingBean, AbstractBeanDefinition bd) { + + // 是否存在 singleton 属性 + if (ele.hasAttribute(SINGLETON_ATTRIBUTE)) { + error("Old 1.x 'singleton' attribute in use - upgrade to 'scope' declaration", ele); + } + // 是否存在 scope 属性 + else if (ele.hasAttribute(SCOPE_ATTRIBUTE)) { + // 设置 scope 属性 + bd.setScope(ele.getAttribute(SCOPE_ATTRIBUTE)); + } + // bean 定义是否为空 + else if (containingBean != null) { + // Take default from containing bean in case of an inner bean definition. + // 设置 bean definition 中的 scope + bd.setScope(containingBean.getScope()); + } + + // 是否存在 abstract 属性 + if (ele.hasAttribute(ABSTRACT_ATTRIBUTE)) { + // 设置 abstract 属性 + bd.setAbstract(TRUE_VALUE.equals(ele.getAttribute(ABSTRACT_ATTRIBUTE))); + } + + // 获取 lazy-init 属性 + String lazyInit = ele.getAttribute(LAZY_INIT_ATTRIBUTE); + // 是否是默认的 lazy-init 属性 + if (isDefaultValue(lazyInit)) { + // 获取默认值 + lazyInit = this.defaults.getLazyInit(); + } + // 设置 lazy-init 属性 + bd.setLazyInit(TRUE_VALUE.equals(lazyInit)); + + // 获取注入方式 + String autowire = ele.getAttribute(AUTOWIRE_ATTRIBUTE); + // 设置注入方式 + bd.setAutowireMode(getAutowireMode(autowire)); + + // 依赖的bean + if (ele.hasAttribute(DEPENDS_ON_ATTRIBUTE)) { + String dependsOn = ele.getAttribute(DEPENDS_ON_ATTRIBUTE); + bd.setDependsOn(StringUtils.tokenizeToStringArray(dependsOn, MULTI_VALUE_ATTRIBUTE_DELIMITERS)); + } + + // autowire-candidate 是否自动注入判断 + String autowireCandidate = ele.getAttribute(AUTOWIRE_CANDIDATE_ATTRIBUTE); + if (isDefaultValue(autowireCandidate)) { + String candidatePattern = this.defaults.getAutowireCandidates(); + if (candidatePattern != null) { + String[] patterns = StringUtils.commaDelimitedListToStringArray(candidatePattern); + // * 匹配 设置数据 + bd.setAutowireCandidate(PatternMatchUtils.simpleMatch(patterns, beanName)); + } + } + else { + bd.setAutowireCandidate(TRUE_VALUE.equals(autowireCandidate)); + } + + // 获取 primary 书信 + if (ele.hasAttribute(PRIMARY_ATTRIBUTE)) { + bd.setPrimary(TRUE_VALUE.equals(ele.getAttribute(PRIMARY_ATTRIBUTE))); + } + + // 获取 init-method 属性 + if (ele.hasAttribute(INIT_METHOD_ATTRIBUTE)) { + String initMethodName = ele.getAttribute(INIT_METHOD_ATTRIBUTE); + bd.setInitMethodName(initMethodName); + } + // 没有 init-method 的情况处理 + else if (this.defaults.getInitMethod() != null) { + bd.setInitMethodName(this.defaults.getInitMethod()); + bd.setEnforceInitMethod(false); + } + + // 获取 destroy-method 属性 + if (ele.hasAttribute(DESTROY_METHOD_ATTRIBUTE)) { + String destroyMethodName = ele.getAttribute(DESTROY_METHOD_ATTRIBUTE); + bd.setDestroyMethodName(destroyMethodName); + } + // 没有 destroy-method 的情况处理 + else if (this.defaults.getDestroyMethod() != null) { + bd.setDestroyMethodName(this.defaults.getDestroyMethod()); + bd.setEnforceDestroyMethod(false); + } + + // 获取 factory-method 属性 + if (ele.hasAttribute(FACTORY_METHOD_ATTRIBUTE)) { + bd.setFactoryMethodName(ele.getAttribute(FACTORY_METHOD_ATTRIBUTE)); + } + // 获取 factory-bean 属性 + if (ele.hasAttribute(FACTORY_BEAN_ATTRIBUTE)) { + bd.setFactoryBeanName(ele.getAttribute(FACTORY_BEAN_ATTRIBUTE)); + } + + return bd; +} +``` + + + + + +### parseMetaElements + + + +- `org.springframework.beans.factory.xml.BeanDefinitionParserDelegate#parseMetaElements` + +- 设置元数据. + + 标签`meta`的解析 + +```java +public void parseMetaElements(Element ele, BeanMetadataAttributeAccessor attributeAccessor) { + // 获取下级标签 + NodeList nl = ele.getChildNodes(); + // 循环子标签 + for (int i = 0; i < nl.getLength(); i++) { + Node node = nl.item(i); + // 设置数据 + if (isCandidateElement(node) && nodeNameEquals(node, META_ELEMENT)) { + Element metaElement = (Element) node; + // 获取 key 属性 + String key = metaElement.getAttribute(KEY_ATTRIBUTE); + // 获取 value 属性 + String value = metaElement.getAttribute(VALUE_ATTRIBUTE); + // 元数据对象设置 + BeanMetadataAttribute attribute = new BeanMetadataAttribute(key, value); + // 设置 source + attribute.setSource(extractSource(metaElement)); + // 信息添加 + attributeAccessor.addMetadataAttribute(attribute); + } + } +} ``` -### 测试用例 + + +使用案例 ```xml - - - - - - - - + + + ``` -![image-20191231165638975](/image/spring/image-20191231165638975.png) -## parseReplacedMethodSubElements ```java - /** - * {@code } - * Parse replaced-method sub-elements of the given bean element. - */ - public void parseReplacedMethodSubElements(Element beanEle, MethodOverrides overrides) { - NodeList nl = beanEle.getChildNodes(); - for (int i = 0; i < nl.getLength(); i++) { - Node node = nl.item(i); - if (isCandidateElement(node) && nodeNameEquals(node, REPLACED_METHOD_ELEMENT)) { - Element replacedMethodEle = (Element) node; - String name = replacedMethodEle.getAttribute(NAME_ATTRIBUTE); - String callback = replacedMethodEle.getAttribute(REPLACER_ATTRIBUTE); - // 转换成JAVA对象 - ReplaceOverride replaceOverride = new ReplaceOverride(name, callback); - // Look for arg-type match elements. - // 参数解析 解析 - List argTypeEles = DomUtils.getChildElementsByTagName(replacedMethodEle, ARG_TYPE_ELEMENT); - for (Element argTypeEle : argTypeEles) { - String match = argTypeEle.getAttribute(ARG_TYPE_MATCH_ATTRIBUTE); - match = (StringUtils.hasText(match) ? match : DomUtils.getTextValue(argTypeEle)); - if (StringUtils.hasText(match)) { - replaceOverride.addTypeIdentifier(match); - } - } - replaceOverride.setSource(extractSource(replacedMethodEle)); - overrides.addOverride(replaceOverride); - } - } - } +ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("META-INF/beans/spring-lookup-method.xml"); +ConfigurableListableBeanFactory beanFactory = context.getBeanFactory(); +BeanDefinition apple = beanFactory.getBeanDefinition("apple"); +Object attribute = apple.getAttribute("meta-key"); +System.out.println(attribute); ``` -### 测试用例 -编写方法`dis` + +### parseLookupOverrideSubElements + +- `org.springframework.beans.factory.xml.BeanDefinitionParserDelegate#parseLookupOverrideSubElements` + +- 解析标签 + + `lookup-method` + + ```java -public class Person { - private String name; - private Apple apple; - private Integer age; - - public void dis() { - System.out.println("dis"); - } +public void parseLookupOverrideSubElements(Element beanEle, MethodOverrides overrides) { + // 获取子标签 + NodeList nl = beanEle.getChildNodes(); + for (int i = 0; i < nl.getLength(); i++) { + Node node = nl.item(i); + // 是否有 lookup-method 属性 + if (isCandidateElement(node) && nodeNameEquals(node, LOOKUP_METHOD_ELEMENT)) { + Element ele = (Element) node; + // 获取 name 属性 + String methodName = ele.getAttribute(NAME_ATTRIBUTE); + // 获取 bean 属性 + String beanRef = ele.getAttribute(BEAN_ELEMENT); + // 创建 覆盖依赖 + LookupOverride override = new LookupOverride(methodName, beanRef); + // 设置 source + override.setSource(extractSource(ele)); + overrides.addOverride(override); + } + } } ``` -​ 编写一个替换`dis`方法的类 + + +使用案例 + +```xml + + + + + + + + +``` ```java -public class Rc implements MethodReplacer { - @Override - public Object reimplement(Object obj, Method method, Object[] args) throws Throwable { - System.out.println("替换原来的方法"); - return null; - } +public class LookupMain { + public static void main(String[] args) { + ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("META-INF/beans/spring-lookup-method.xml"); + Shop shop = context.getBean("shop", Shop.class); + System.out.println(shop.getFruits().getName()); + } } ``` -xml 配置 + + + + +### parseReplacedMethodSubElements + +- `org.springframework.beans.factory.xml.BeanDefinitionParserDelegate#parseReplacedMethodSubElements` + +- 解析标签 + + `replaced-method` ```java - - +public void parseReplacedMethodSubElements(Element beanEle, MethodOverrides overrides) { + // 子节点获取 + NodeList nl = beanEle.getChildNodes(); + for (int i = 0; i < nl.getLength(); i++) { + Node node = nl.item(i); + // 是否包含 replaced-method 属性 + if (isCandidateElement(node) && nodeNameEquals(node, REPLACED_METHOD_ELEMENT)) { + Element replacedMethodEle = (Element) node; + // 获取 name 属性 + String name = replacedMethodEle.getAttribute(NAME_ATTRIBUTE); + // 获取 replacer + String callback = replacedMethodEle.getAttribute(REPLACER_ATTRIBUTE); + // 对象组装 + ReplaceOverride replaceOverride = new ReplaceOverride(name, callback); + // Look for arg-type match elements. + // 子节点属性 + // 处理 arg-type 标签 + List argTypeEles = DomUtils.getChildElementsByTagName(replacedMethodEle, ARG_TYPE_ELEMENT); + + for (Element argTypeEle : argTypeEles) { + // 获取 match 数据值 + String match = argTypeEle.getAttribute(ARG_TYPE_MATCH_ATTRIBUTE); + // match 信息设置 + match = (StringUtils.hasText(match) ? match : DomUtils.getTextValue(argTypeEle)); + if (StringUtils.hasText(match)) { + // 添加类型标识 + replaceOverride.addTypeIdentifier(match); + } + } + // 设置 source + replaceOverride.setSource(extractSource(replacedMethodEle)); + // 重载列表添加 + overrides.addOverride(replaceOverride); + } + } +} +``` + + + +- 使用案例 + + + +```xml + + + + + String + + + + + + + + ``` -![image-20200101093742238](/image/spring/image-20200101093742238.png) -## parseConstructorArgElements ```java - public void parseConstructorArgElements(Element beanEle, BeanDefinition bd) { - NodeList nl = beanEle.getChildNodes(); - for (int i = 0; i < nl.getLength(); i++) { - Node node = nl.item(i); - if (isCandidateElement(node) && nodeNameEquals(node, CONSTRUCTOR_ARG_ELEMENT)) { - parseConstructorArgElement((Element) node, bd); - } - } - } +public class MethodReplacerApple implements MethodReplacer { + @Override + public Object reimplement(Object obj, Method method, Object[] args) throws Throwable { + System.out.println("方法替换"); + return obj; + } +} +``` + +**replacer需要使用MethodReplacer实现类** + + + + + + + +### parseConstructorArgElements + +- `org.springframework.beans.factory.xml.BeanDefinitionParserDelegate#parseConstructorArgElements` + +- 解析`constructor-arg`标签 + + ``` +public void parseConstructorArgElements(Element beanEle, BeanDefinition bd) { + // 获取 + NodeList nl = beanEle.getChildNodes(); + for (int i = 0; i < nl.getLength(); i++) { + Node node = nl.item(i); + if (isCandidateElement(node) && nodeNameEquals(node, CONSTRUCTOR_ARG_ELEMENT)) { + // 解析 constructor-arg 下级标签 + parseConstructorArgElement((Element) node, bd); + } + } +} +``` + + + + ```java - /** - * 解析 constructor-arg 元素 - * {@code } - * Parse a constructor-arg element. - */ - public void parseConstructorArgElement(Element ele, BeanDefinition bd) { - String indexAttr = ele.getAttribute(INDEX_ATTRIBUTE); - String typeAttr = ele.getAttribute(TYPE_ATTRIBUTE); - String nameAttr = ele.getAttribute(NAME_ATTRIBUTE); - // 判断是否存在 index 属性 - if (StringUtils.hasLength(indexAttr)) { - try { - int index = Integer.parseInt(indexAttr); - if (index < 0) { - error("'index' cannot be lower than 0", ele); - } - else { - try { - // ConstructorArgumentEntry 插入parseState - this.parseState.push(new ConstructorArgumentEntry(index)); - Object value = parsePropertyValue(ele, bd, null); - // 转换成JAVA对象 - ConstructorArgumentValues.ValueHolder valueHolder = new ConstructorArgumentValues.ValueHolder(value); - if (StringUtils.hasLength(typeAttr)) { - valueHolder.setType(typeAttr); - } - if (StringUtils.hasLength(nameAttr)) { - valueHolder.setName(nameAttr); - } - valueHolder.setSource(extractSource(ele)); - // 不允许重复指定相同参数 - if (bd.getConstructorArgumentValues().hasIndexedArgumentValue(index)) { - error("Ambiguous constructor-arg entries for index " + index, ele); - } - else { - bd.getConstructorArgumentValues().addIndexedArgumentValue(index, valueHolder); - } - } - finally { - this.parseState.pop(); - } - } - } - catch (NumberFormatException ex) { - error("Attribute 'index' of tag 'constructor-arg' must be an integer", ele); - } - } - else { +public void parseConstructorArgElement(Element ele, BeanDefinition bd) { + // 获取 index 属性 + String indexAttr = ele.getAttribute(INDEX_ATTRIBUTE); + // 获取 type 属性 + String typeAttr = ele.getAttribute(TYPE_ATTRIBUTE); + // 获取 name 属性 + String nameAttr = ele.getAttribute(NAME_ATTRIBUTE); + if (StringUtils.hasLength(indexAttr)) { + try { + // 构造参数的所以未知 + int index = Integer.parseInt(indexAttr); + if (index < 0) { + error("'index' cannot be lower than 0", ele); + } + else { try { - this.parseState.push(new ConstructorArgumentEntry()); - Object value = parsePropertyValue(ele, bd, null); - ConstructorArgumentValues.ValueHolder valueHolder = new ConstructorArgumentValues.ValueHolder(value); - if (StringUtils.hasLength(typeAttr)) { - valueHolder.setType(typeAttr); - } - if (StringUtils.hasLength(nameAttr)) { - valueHolder.setName(nameAttr); - } - valueHolder.setSource(extractSource(ele)); - bd.getConstructorArgumentValues().addGenericArgumentValue(valueHolder); + this.parseState.push(new ConstructorArgumentEntry(index)); + // 解析 property 标签 + Object value = parsePropertyValue(ele, bd, null); + // 创建 构造函数的 属性控制类 + ConstructorArgumentValues.ValueHolder valueHolder = new ConstructorArgumentValues.ValueHolder(value); + if (StringUtils.hasLength(typeAttr)) { + // 类型设置 + valueHolder.setType(typeAttr); + } + if (StringUtils.hasLength(nameAttr)) { + // 名称设置 + valueHolder.setName(nameAttr); + } + // 源设置 + valueHolder.setSource(extractSource(ele)); + if (bd.getConstructorArgumentValues().hasIndexedArgumentValue(index)) { + error("Ambiguous constructor-arg entries for index " + index, ele); + } + else { + // 添加 构造函数信息 + bd.getConstructorArgumentValues().addIndexedArgumentValue(index, valueHolder); + } } finally { - this.parseState.pop(); + this.parseState.pop(); } - } - } - + } + } + catch (NumberFormatException ex) { + error("Attribute 'index' of tag 'constructor-arg' must be an integer", ele); + } + } + else { + try { + this.parseState.push(new ConstructorArgumentEntry()); + // 解析 property 标签 + Object value = parsePropertyValue(ele, bd, null); + // 创建 构造函数的 属性控制类 + ConstructorArgumentValues.ValueHolder valueHolder = new ConstructorArgumentValues.ValueHolder(value); + if (StringUtils.hasLength(typeAttr)) { + // 类型设置 + valueHolder.setType(typeAttr); + } + if (StringUtils.hasLength(nameAttr)) { + // 名称设置 + valueHolder.setName(nameAttr); + } + // 源设置 + valueHolder.setSource(extractSource(ele)); + // 添加 构造函数信息 + bd.getConstructorArgumentValues().addGenericArgumentValue(valueHolder); + } + finally { + this.parseState.pop(); + } + } +} ``` -```JAVA - /** - * Get the value of a property element. May be a list etc. - * Also used for constructor arguments, "propertyName" being null in this case. - */ - @Nullable - public Object parsePropertyValue(Element ele, BeanDefinition bd, @Nullable String propertyName) { - String elementName = (propertyName != null ? - " element for property '" + propertyName + "'" : - " element"); - - // Should only have one child element: ref, value, list, etc. - NodeList nl = ele.getChildNodes(); - Element subElement = null; - for (int i = 0; i < nl.getLength(); i++) { - Node node = nl.item(i); - // 不处理 element 节点名称 = description 和 meta - if (node instanceof Element && !nodeNameEquals(node, DESCRIPTION_ELEMENT) && - !nodeNameEquals(node, META_ELEMENT)) { - // Child element is what we're looking for. - if (subElement != null) { - error(elementName + " must not contain more than one sub-element", ele); - } - else { - subElement = (Element) node; - } - } - } - - // 判断是否存在 ref 属性 - boolean hasRefAttribute = ele.hasAttribute(REF_ATTRIBUTE); - // 判断是否 value 属性 - boolean hasValueAttribute = ele.hasAttribute(VALUE_ATTRIBUTE); - // 判断1: ref属性存在 value 属性 或者 ref 和 value 有一个存在并且有 下级节点 抛出异常 - if ((hasRefAttribute && hasValueAttribute) || - ((hasRefAttribute || hasValueAttribute) && subElement != null)) { - error(elementName + - " is only allowed to contain either 'ref' attribute OR 'value' attribute OR sub-element", ele); - } - - // 判断2: 存在 ref 返回 ref 的值 - if (hasRefAttribute) { - String refName = ele.getAttribute(REF_ATTRIBUTE); - if (!StringUtils.hasText(refName)) { - error(elementName + " contains empty 'ref' attribute", ele); - } - RuntimeBeanReference ref = new RuntimeBeanReference(refName); - ref.setSource(extractSource(ele)); - return ref; - } - // 判断3: 存在 value 返回 value 的值 - else if (hasValueAttribute) { - TypedStringValue valueHolder = new TypedStringValue(ele.getAttribute(VALUE_ATTRIBUTE)); - valueHolder.setSource(extractSource(ele)); - return valueHolder; - } - else if (subElement != null) { - // 下级标签解析 - return parsePropertySubElement(subElement, bd); - } - else { - // 没有抛出异常 - // Neither child element nor "ref" or "value" attribute found. - error(elementName + " must specify a ref or value", ele); - return null; - } - } -``` -### 测试用例 +### parseConstructorArgElement -- 编辑构造函数 +- `org.springframework.beans.factory.xml.BeanDefinitionParserDelegate#parseConstructorArgElement` - ```java - public class Person { - private String name; - private Apple apple; - private Integer age; +- 解析 constructor-arg 下级标签 - public Person() { +```java +@Nullable +public Object parsePropertyValue(Element ele, BeanDefinition bd, @Nullable String propertyName) { + String elementName = (propertyName != null ? + " element for property '" + propertyName + "'" : + " element"); + + // Should only have one child element: ref, value, list, etc. + NodeList nl = ele.getChildNodes(); + Element subElement = null; + for (int i = 0; i < nl.getLength(); i++) { + Node node = nl.item(i); + if (node instanceof Element && !nodeNameEquals(node, DESCRIPTION_ELEMENT) && + !nodeNameEquals(node, META_ELEMENT)) { + // Child element is what we're looking for. + if (subElement != null) { + error(elementName + " must not contain more than one sub-element", ele); + } + else { + subElement = (Element) node; + } } - - public Person(Integer age) { - this.age = age; + } + + // ref 属性是否存在 + boolean hasRefAttribute = ele.hasAttribute(REF_ATTRIBUTE); + // value 属性是否存在 + boolean hasValueAttribute = ele.hasAttribute(VALUE_ATTRIBUTE); + if ((hasRefAttribute && hasValueAttribute) || + ((hasRefAttribute || hasValueAttribute) && subElement != null)) { + error(elementName + + " is only allowed to contain either 'ref' attribute OR 'value' attribute OR sub-element", ele); + } + + if (hasRefAttribute) { + // 获取 ref 属性值 + String refName = ele.getAttribute(REF_ATTRIBUTE); + if (!StringUtils.hasText(refName)) { + error(elementName + " contains empty 'ref' attribute", ele); } + // 创建 连接对象 + RuntimeBeanReference ref = new RuntimeBeanReference(refName); + + ref.setSource(extractSource(ele)); + return ref; + } + else if (hasValueAttribute) { + // 获取 value + TypedStringValue valueHolder = new TypedStringValue(ele.getAttribute(VALUE_ATTRIBUTE)); + valueHolder.setSource(extractSource(ele)); + return valueHolder; + } + else if (subElement != null) { + return parsePropertySubElement(subElement, bd); + } + else { + // Neither child element nor "ref" or "value" attribute found. + error(elementName + " must specify a ref or value", ele); + return null; + } +} +``` - ``` -- 添加配置 - ```xml - - ``` -![image-20200101100906778](/image/spring/image-20200101100906778.png) +### parsePropertySubElement -## parsePropertyElements +- `org.springframework.beans.factory.xml.BeanDefinitionParserDelegate#parsePropertySubElement(org.w3c.dom.Element, org.springframework.beans.factory.config.BeanDefinition)` ```java -public void parsePropertyElements(Element beanEle, BeanDefinition bd) { - NodeList nl = beanEle.getChildNodes(); - for (int i = 0; i < nl.getLength(); i++) { - Node node = nl.item(i); - if (isCandidateElement(node) && nodeNameEquals(node, PROPERTY_ELEMENT)) { - parsePropertyElement((Element) node, bd); - } - } - } +@Nullable +public Object parsePropertySubElement(Element ele, @Nullable BeanDefinition bd) { + // 解析 property 下级标签 + return parsePropertySubElement(ele, bd, null); +} ``` -```java - /** - * 解析 {@code } - * Parse a property element. - */ - public void parsePropertyElement(Element ele, BeanDefinition bd) { - String propertyName = ele.getAttribute(NAME_ATTRIBUTE); - if (!StringUtils.hasLength(propertyName)) { - error("Tag 'property' must have a 'name' attribute", ele); - return; - } - this.parseState.push(new PropertyEntry(propertyName)); - try { - if (bd.getPropertyValues().contains(propertyName)) { - error("Multiple 'property' definitions for property '" + propertyName + "'", ele); - return; - } - Object val = parsePropertyValue(ele, bd, propertyName); - // 转换JAVA 对象 - PropertyValue pv = new PropertyValue(propertyName, val); - parseMetaElements(ele, pv); - pv.setSource(extractSource(ele)); - bd.getPropertyValues().addPropertyValue(pv); - } - finally { - this.parseState.pop(); - } - } -``` -### 测试用例 -xml -```xml - - - +### parsePropertySubElement + +- `org.springframework.beans.factory.xml.BeanDefinitionParserDelegate#parsePropertySubElement(org.w3c.dom.Element, org.springframework.beans.factory.config.BeanDefinition, java.lang.String)` + ``` +@Nullable +public Object parsePropertySubElement(Element ele, @Nullable BeanDefinition bd, @Nullable String defaultValueType) { + if (!isDefaultNamespace(ele)) { + // 嵌套分析 + return parseNestedCustomElement(ele, bd); + } + else if (nodeNameEquals(ele, BEAN_ELEMENT)) { + // 解析 bean 标签 + BeanDefinitionHolder nestedBd = parseBeanDefinitionElement(ele, bd); + if (nestedBd != null) { + // 装饰 bean define + nestedBd = decorateBeanDefinitionIfRequired(ele, nestedBd, bd); + } + return nestedBd; + } + // ref 名称判断 + else if (nodeNameEquals(ele, REF_ELEMENT)) { + // A generic reference to any name of any bean. + // 获取 ref 属性 + String refName = ele.getAttribute(BEAN_REF_ATTRIBUTE); + boolean toParent = false; + if (!StringUtils.hasLength(refName)) { + // A reference to the id of another bean in a parent context. + // 获取 parent 属性 + refName = ele.getAttribute(PARENT_REF_ATTRIBUTE); + toParent = true; + if (!StringUtils.hasLength(refName)) { + error("'bean' or 'parent' is required for element", ele); + return null; + } + } + if (!StringUtils.hasText(refName)) { + error(" element contains empty target attribute", ele); + return null; + } + // bean 连接对象创建 + RuntimeBeanReference ref = new RuntimeBeanReference(refName, toParent); + ref.setSource(extractSource(ele)); + return ref; + } + else if (nodeNameEquals(ele, IDREF_ELEMENT)) { + return parseIdRefElement(ele); + } + else if (nodeNameEquals(ele, VALUE_ELEMENT)) { + return parseValueElement(ele, defaultValueType); + } + else if (nodeNameEquals(ele, NULL_ELEMENT)) { + // It's a distinguished null value. Let's wrap it in a TypedStringValue + // object in order to preserve the source location. + TypedStringValue nullHolder = new TypedStringValue(null); + nullHolder.setSource(extractSource(ele)); + return nullHolder; + } + else if (nodeNameEquals(ele, ARRAY_ELEMENT)) { + return parseArrayElement(ele, bd); + } + else if (nodeNameEquals(ele, LIST_ELEMENT)) { + return parseListElement(ele, bd); + } + else if (nodeNameEquals(ele, SET_ELEMENT)) { + return parseSetElement(ele, bd); + } + else if (nodeNameEquals(ele, MAP_ELEMENT)) { + return parseMapElement(ele, bd); + } + else if (nodeNameEquals(ele, PROPS_ELEMENT)) { + return parsePropsElement(ele); + } + else { + error("Unknown property sub-element: [" + ele.getNodeName() + "]", ele); + return null; + } +} +``` + + + + -![image-20200101111755022](/image/spring/image-20200101111755022.png) +#### parseIdRefElement +- `org.springframework.beans.factory.xml.BeanDefinitionParserDelegate#parseIdRefElement` -## parseQualifierElements ```java -public void parseQualifierElements(Element beanEle, AbstractBeanDefinition bd) { - NodeList nl = beanEle.getChildNodes(); - for (int i = 0; i < nl.getLength(); i++) { - Node node = nl.item(i); - if (isCandidateElement(node) && nodeNameEquals(node, QUALIFIER_ELEMENT)) { - parseQualifierElement((Element) node, bd); - } - } - } +@Nullable +public Object parseIdRefElement(Element ele) { + // A generic reference to any name of any bean. + // 获取 bean 属性 + String refName = ele.getAttribute(BEAN_REF_ATTRIBUTE); + if (!StringUtils.hasLength(refName)) { + error("'bean' is required for element", ele); + return null; + } + if (!StringUtils.hasText(refName)) { + error(" element contains empty target attribute", ele); + return null; + } + // 设置 bean 链接对象 + RuntimeBeanNameReference ref = new RuntimeBeanNameReference(refName); + // 设置原 + ref.setSource(extractSource(ele)); + return ref; +} ``` -```java - /** - * Parse a qualifier element. - */ - public void parseQualifierElement(Element ele, AbstractBeanDefinition bd) { - String typeName = ele.getAttribute(TYPE_ATTRIBUTE); - // 判断是否有类型 - if (!StringUtils.hasLength(typeName)) { - error("Tag 'qualifier' must have a 'type' attribute", ele); - return; - } - // 创建并且放入 parseState - this.parseState.push(new QualifierEntry(typeName)); - try { - AutowireCandidateQualifier qualifier = new AutowireCandidateQualifier(typeName); - qualifier.setSource(extractSource(ele)); - String value = ele.getAttribute(VALUE_ATTRIBUTE); - // 判断是否有值 - if (StringUtils.hasLength(value)) { - qualifier.setAttribute(AutowireCandidateQualifier.VALUE_KEY, value); - } - // 下级节点 - NodeList nl = ele.getChildNodes(); - for (int i = 0; i < nl.getLength(); i++) { - Node node = nl.item(i); - if (isCandidateElement(node) && nodeNameEquals(node, QUALIFIER_ATTRIBUTE_ELEMENT)) { - Element attributeEle = (Element) node; - // 获取 下级biao'qia - String attributeName = attributeEle.getAttribute(KEY_ATTRIBUTE); - String attributeValue = attributeEle.getAttribute(VALUE_ATTRIBUTE); - // 判断是否有 key 和 value - if (StringUtils.hasLength(attributeName) && StringUtils.hasLength(attributeValue)) { - // 转换成JAVA对象 - BeanMetadataAttribute attribute = new BeanMetadataAttribute(attributeName, attributeValue); - attribute.setSource(extractSource(attributeEle)); - qualifier.addMetadataAttribute(attribute); - } - else { - // 没有抛出异常 - error("Qualifier 'attribute' tag must have a 'name' and 'value'", attributeEle); - return; - } - } - } - bd.addQualifier(qualifier); - } - finally { - this.parseState.pop(); - } - } + + +#### parseValueElement + +- `org.springframework.beans.factory.xml.BeanDefinitionParserDelegate#parseValueElement` + + + +```JAVA + public Object parseValueElement(Element ele, @Nullable String defaultTypeName) { + // It's a literal value. + // 获取 xml 中的文本变量 + String value = DomUtils.getTextValue(ele); + // 获取 type 属性 + String specifiedTypeName = ele.getAttribute(TYPE_ATTRIBUTE); + // 类型 + String typeName = specifiedTypeName; + if (!StringUtils.hasText(typeName)) { + typeName = defaultTypeName; + } + try { + // 创建类型值 + TypedStringValue typedValue = buildTypedStringValue(value, typeName); + typedValue.setSource(extractSource(ele)); + typedValue.setSpecifiedTypeName(specifiedTypeName); + return typedValue; + } + catch (ClassNotFoundException ex) { + error("Type class [" + typeName + "] not found for element", ele, ex); + return value; + } + } ``` -### 测试用例 -- 编写一个注解 + + + +##### buildTypedStringValue + +- `org.springframework.beans.factory.xml.BeanDefinitionParserDelegate#buildTypedStringValue` +- 构造对象, 没有创建对象 ```java -/** - * 在spring-config.xml中配置 ,使用时通过 status + quality 来引入具体的bean - */ -@Target({ElementType.FIELD, ElementType.METHOD, - ElementType.TYPE, ElementType.PARAMETER}) -@Retention(RetentionPolicy.RUNTIME) -@Qualifier -public @interface PersonQualifier { +protected TypedStringValue buildTypedStringValue(String value, @Nullable String targetTypeName) + throws ClassNotFoundException { + // class loader + ClassLoader classLoader = this.readerContext.getBeanClassLoader(); + TypedStringValue typedValue; + if (!StringUtils.hasText(targetTypeName)) { + typedValue = new TypedStringValue(value); + } + else if (classLoader != null) { + // 目标类 + Class targetType = ClassUtils.forName(targetTypeName, classLoader); + // 构造 + typedValue = new TypedStringValue(value, targetType); + } + else { + // 构造 + typedValue = new TypedStringValue(value, targetTypeName); + } + return typedValue; +} +``` - String status(); +#### parseArrayElement - String quality(); +```java +public Object parseArrayElement(Element arrayEle, @Nullable BeanDefinition bd) { + // 获取 value-type 属性 + String elementType = arrayEle.getAttribute(VALUE_TYPE_ATTRIBUTE); + // 子节点 + NodeList nl = arrayEle.getChildNodes(); + // 合并 array 的类 + ManagedArray target = new ManagedArray(elementType, nl.getLength()); + target.setSource(extractSource(arrayEle)); + target.setElementTypeName(elementType); + target.setMergeEnabled(parseMergeAttribute(arrayEle)); + // 处理 collection 节点 + parseCollectionElements(nl, target, bd, elementType); + return target; } ``` -```JAVA -public class PersonS { - private String personName; - public String getPersonName() { - return personName; - } - public void setPersonName(String personName) { - this.personName = personName; - } +#### parseListElement + +```java +public List parseListElement(Element collectionEle, @Nullable BeanDefinition bd) { + String defaultElementType = collectionEle.getAttribute(VALUE_TYPE_ATTRIBUTE); + NodeList nl = collectionEle.getChildNodes(); + ManagedList target = new ManagedList<>(nl.getLength()); + target.setSource(extractSource(collectionEle)); + target.setElementTypeName(defaultElementType); + target.setMergeEnabled(parseMergeAttribute(collectionEle)); + parseCollectionElements(nl, target, bd, defaultElementType); + return target; } ``` -```JAVA +#### parseSetElement + +```java +public Set parseSetElement(Element collectionEle, @Nullable BeanDefinition bd) { + String defaultElementType = collectionEle.getAttribute(VALUE_TYPE_ATTRIBUTE); + NodeList nl = collectionEle.getChildNodes(); + ManagedSet target = new ManagedSet<>(nl.getLength()); + target.setSource(extractSource(collectionEle)); + target.setElementTypeName(defaultElementType); + target.setMergeEnabled(parseMergeAttribute(collectionEle)); + parseCollectionElements(nl, target, bd, defaultElementType); + return target; +} +``` + + -import org.springframework.beans.factory.annotation.Autowired; -public class PersonService { - @Autowired -// @PersonQualifier(status = "status_teacher", quality = "quality_teacher") - @PersonQualifier(status = "status_student", quality = "quality_student") - private PersonS personS; - public PersonS getPerson() { - return personS; - } +##### parseCollectionElements - public void setPerson(PersonS person) { - this.personS = person; - } +- `parseArrayElement`、`parseListElement`、`parseSetElement` 都围绕者下面这个方法进行数据合并 + +```java +protected void parseCollectionElements( + NodeList elementNodes, Collection target, @Nullable BeanDefinition bd, String defaultElementType) { + + for (int i = 0; i < elementNodes.getLength(); i++) { + Node node = elementNodes.item(i); + if (node instanceof Element && !nodeNameEquals(node, DESCRIPTION_ELEMENT)) { + // 处理子节点 + target.add(parsePropertySubElement((Element) node, bd, defaultElementType)); + } + } } ``` -```JAVA -public class Student extends PersonS { - private String stdLocation; - public String getStdLocation() { - return stdLocation; - } - public void setStdLocation(String stdLocation) { - this.stdLocation = stdLocation; - } +#### parseMapElement + +```java +public Map parseMapElement(Element mapEle, @Nullable BeanDefinition bd) { + // key-type 属性获取 + String defaultKeyType = mapEle.getAttribute(KEY_TYPE_ATTRIBUTE); + // value-type 属性互殴去 + String defaultValueType = mapEle.getAttribute(VALUE_TYPE_ATTRIBUTE); + + // entry 标签获取 + List entryEles = DomUtils.getChildElementsByTagName(mapEle, ENTRY_ELEMENT); + // 合并 map 对象 + ManagedMap map = new ManagedMap<>(entryEles.size()); + map.setSource(extractSource(mapEle)); + map.setKeyTypeName(defaultKeyType); + map.setValueTypeName(defaultValueType); + map.setMergeEnabled(parseMergeAttribute(mapEle)); + + // 循环 entry 节点 + for (Element entryEle : entryEles) { + // Should only have one value child element: ref, value, list, etc. + // Optionally, there might be a key child element. + NodeList entrySubNodes = entryEle.getChildNodes(); + Element keyEle = null; + Element valueEle = null; + for (int j = 0; j < entrySubNodes.getLength(); j++) { + Node node = entrySubNodes.item(j); + if (node instanceof Element) { + Element candidateEle = (Element) node; + // 节点名称是否为 key + if (nodeNameEquals(candidateEle, KEY_ELEMENT)) { + if (keyEle != null) { + error(" element is only allowed to contain one sub-element", entryEle); + } + else { + keyEle = candidateEle; + } + } + else { + // Child element is what we're looking for. + if (nodeNameEquals(candidateEle, DESCRIPTION_ELEMENT)) { + // the element is a -> ignore it + } + else if (valueEle != null) { + error(" element must not contain more than one value sub-element", entryEle); + } + else { + valueEle = candidateEle; + } + } + } + } + + // Extract key from attribute or sub-element. + Object key = null; + // key 属性 + boolean hasKeyAttribute = entryEle.hasAttribute(KEY_ATTRIBUTE); + // key-ref 属性 + boolean hasKeyRefAttribute = entryEle.hasAttribute(KEY_REF_ATTRIBUTE); + if ((hasKeyAttribute && hasKeyRefAttribute) || + (hasKeyAttribute || hasKeyRefAttribute) && keyEle != null) { + error(" element is only allowed to contain either " + + "a 'key' attribute OR a 'key-ref' attribute OR a sub-element", entryEle); + } + if (hasKeyAttribute) { + // TypedStringValue 构建 + key = buildTypedStringValueForMap(entryEle.getAttribute(KEY_ATTRIBUTE), defaultKeyType, entryEle); + } + else if (hasKeyRefAttribute) { + // key-ref 属性获取 + String refName = entryEle.getAttribute(KEY_REF_ATTRIBUTE); + if (!StringUtils.hasText(refName)) { + error(" element contains empty 'key-ref' attribute", entryEle); + } + // 创建 bean 连接对象 + RuntimeBeanReference ref = new RuntimeBeanReference(refName); + ref.setSource(extractSource(entryEle)); + key = ref; + } + else if (keyEle != null) { + // 获取 key 数据 + key = parseKeyElement(keyEle, bd, defaultKeyType); + } + else { + error(" element must specify a key", entryEle); + } + + // Extract value from attribute or sub-element. + Object value = null; + // value 属性是否存在 + boolean hasValueAttribute = entryEle.hasAttribute(VALUE_ATTRIBUTE); + // value-ref 属性是否存在 + boolean hasValueRefAttribute = entryEle.hasAttribute(VALUE_REF_ATTRIBUTE); + // 是否存在 value-type 属性 + boolean hasValueTypeAttribute = entryEle.hasAttribute(VALUE_TYPE_ATTRIBUTE); + if ((hasValueAttribute && hasValueRefAttribute) || + (hasValueAttribute || hasValueRefAttribute) && valueEle != null) { + error(" element is only allowed to contain either " + + "'value' attribute OR 'value-ref' attribute OR sub-element", entryEle); + } + if ((hasValueTypeAttribute && hasValueRefAttribute) || + (hasValueTypeAttribute && !hasValueAttribute) || + (hasValueTypeAttribute && valueEle != null)) { + error(" element is only allowed to contain a 'value-type' " + + "attribute when it has a 'value' attribute", entryEle); + } + if (hasValueAttribute) { + // 获取 value-type 属性 + String valueType = entryEle.getAttribute(VALUE_TYPE_ATTRIBUTE); + if (!StringUtils.hasText(valueType)) { + // 设置默认value-type + valueType = defaultValueType; + } + // 创建 TypedStringValue + value = buildTypedStringValueForMap(entryEle.getAttribute(VALUE_ATTRIBUTE), valueType, entryEle); + } + else if (hasValueRefAttribute) { + // 获取 value-ref 属性 + String refName = entryEle.getAttribute(VALUE_REF_ATTRIBUTE); + if (!StringUtils.hasText(refName)) { + error(" element contains empty 'value-ref' attribute", entryEle); + } + // 创建 bean 链接对象 + RuntimeBeanReference ref = new RuntimeBeanReference(refName); + ref.setSource(extractSource(entryEle)); + value = ref; + } + else if (valueEle != null) { + value = parsePropertySubElement(valueEle, bd, defaultValueType); + } + else { + error(" element must specify a value", entryEle); + } + + // Add final key and value to the Map. + map.put(key, value); + } + + return map; } ``` -```JAVA -public class Teacher extends PersonS { - private String subject; - public String getSubject() { - return subject; - } - public void setSubject(String subject) { - this.subject = subject; - } + + + + +#### parsePropsElement + + + + + + + +### parsePropertyElement + +- `org.springframework.beans.factory.xml.BeanDefinitionParserDelegate#parsePropertyElement` + +```java +public void parsePropertyElement(Element ele, BeanDefinition bd) { + String propertyName = ele.getAttribute(NAME_ATTRIBUTE); + if (!StringUtils.hasLength(propertyName)) { + error("Tag 'property' must have a 'name' attribute", ele); + return; + } + this.parseState.push(new PropertyEntry(propertyName)); + try { + if (bd.getPropertyValues().contains(propertyName)) { + error("Multiple 'property' definitions for property '" + propertyName + "'", ele); + return; + } + // 解析 property 标签 + Object val = parsePropertyValue(ele, bd, propertyName); + // 构造 PropertyValue 对象 + PropertyValue pv = new PropertyValue(propertyName, val); + // 解析元信息 + parseMetaElements(ele, pv); + pv.setSource(extractSource(ele)); + // 添加 pv 结构 + bd.getPropertyValues().addPropertyValue(pv); + } + finally { + this.parseState.pop(); + } } ``` -```JAVA -public class QualifierSourceCode { - public static void main(String[] args) { - AbstractApplicationContext context = new ClassPathXmlApplicationContext("QualifierSourceCode-beans.xml"); - PersonService service = context.getBean(PersonService.class); - System.out.println(service.getPerson().getPersonName()); - context.close(); - } -} -``` -```XML - - - - - - - - - - - - - - - - - - - - - - - -``` -![image-20200101155539501](/image/spring/image-20200101155539501.png) -### Bean 解析结果 -![image-20200102083512005](/image/spring/image-20200102083512005.png) -## importBeanDefinitionResource +### parseQualifierElements -```JAVA - /** - * 解析{@code } 标签 - * Parse an "import" element and load the bean definitions - * from the given resource into the bean factory. - */ - protected void importBeanDefinitionResource(Element ele) { - // 获取 resource 属性 - String location = ele.getAttribute(RESOURCE_ATTRIBUTE); - // 是否有 resource 属性 - if (!StringUtils.hasText(location)) { - getReaderContext().error("Resource location must not be empty", ele); - return; - } - - // Resolve system properties: e.g. "${user.dir}" - // 获取系统环境,解析路径 - /** - * 1. getReaderContext() 获取{@link XmlReaderContext} - * 2. getEnvironment() 获取环境 - * 3. resolveRequiredPlaceholders(location) 解析占位符${...} - */ - location = getReaderContext().getEnvironment().resolveRequiredPlaceholders(location); - - // 资源存放集合 - Set actualResources = new LinkedHashSet<>(4); - - // Discover whether the location is an absolute or relative URI - // 相对路径 绝对路径的判断 - boolean absoluteLocation = false; - try { - // 判断是相对路径还是绝对路径 - absoluteLocation = ResourcePatternUtils.isUrl(location) || ResourceUtils.toURI(location).isAbsolute(); - } - catch (URISyntaxException ex) { - // cannot convert to an URI, considering the location relative - // unless it is the well-known Spring prefix "classpath*:" - } - - // Absolute or relative? - if (absoluteLocation) { - try { - // 获取import中的数量 - int importCount = getReaderContext().getReader().loadBeanDefinitions(location, actualResources); - if (logger.isTraceEnabled()) { - logger.trace("Imported " + importCount + " bean definitions from URL location [" + location + "]"); - } - } - catch (BeanDefinitionStoreException ex) { - getReaderContext().error( - "Failed to import bean definitions from URL location [" + location + "]", ele, ex); - } - } - else { - // No URL -> considering resource location as relative to the current file. - try { - int importCount; - // 本地地址 - Resource relativeResource = getReaderContext().getResource().createRelative(location); - if (relativeResource.exists()) { - // 此处调用方式和加载一个xml文件相同 - importCount = getReaderContext().getReader().loadBeanDefinitions(relativeResource); - - actualResources.add(relativeResource); - } - else { - String baseLocation = getReaderContext().getResource().getURL().toString(); - importCount = getReaderContext().getReader().loadBeanDefinitions( - StringUtils.applyRelativePath(baseLocation, location), actualResources); - } - if (logger.isTraceEnabled()) { - logger.trace("Imported " + importCount + " bean definitions from relative location [" + location + "]"); - } - } - catch (IOException ex) { - getReaderContext().error("Failed to resolve current resource location", ele, ex); - } - catch (BeanDefinitionStoreException ex) { - getReaderContext().error( - "Failed to import bean definitions from relative location [" + location + "]", ele, ex); - } - } - // 转换数组 - Resource[] actResArray = actualResources.toArray(new Resource[0]); - /*** - * fireImportProcessed()触发import事件, - * 并且通过{@link org.springframework.beans.factory.parsing.ReaderEventListener#importProcessed(ImportDefinition)} 宣布处理结果 - */ - getReaderContext().fireImportProcessed(location, actResArray, extractSource(ele)); - } +- `org.springframework.beans.factory.xml.BeanDefinitionParserDelegate#parseQualifierElements` +- 解析 qualifier 标签和下级标签 +```java +public void parseQualifierElements(Element beanEle, AbstractBeanDefinition bd) { + NodeList nl = beanEle.getChildNodes(); + for (int i = 0; i < nl.getLength(); i++) { + Node node = nl.item(i); + if (isCandidateElement(node) && nodeNameEquals(node, QUALIFIER_ELEMENT)) { + // 单个解析 + parseQualifierElement((Element) node, bd); + } + } +} ``` -![image-20200102085031641](/image/spring/image-20200102085031641.png) -![image-20200102091421516](/image/spring/image-20200102091421516.png) + + + +### parseQualifierElement + +- `org.springframework.beans.factory.xml.BeanDefinitionParserDelegate#parseQualifierElement` + +```java +public void parseQualifierElement(Element ele, AbstractBeanDefinition bd) { + // 获取 type 属性 + String typeName = ele.getAttribute(TYPE_ATTRIBUTE); + if (!StringUtils.hasLength(typeName)) { + error("Tag 'qualifier' must have a 'type' attribute", ele); + return; + } + this.parseState.push(new QualifierEntry(typeName)); + try { + // 自动注入对象创建 + AutowireCandidateQualifier qualifier = new AutowireCandidateQualifier(typeName); + // 设置源 + qualifier.setSource(extractSource(ele)); + // 获取 value 属性 + String value = ele.getAttribute(VALUE_ATTRIBUTE); + if (StringUtils.hasLength(value)) { + // 设置 属性 value , value + qualifier.setAttribute(AutowireCandidateQualifier.VALUE_KEY, value); + } + NodeList nl = ele.getChildNodes(); + for (int i = 0; i < nl.getLength(); i++) { + Node node = nl.item(i); + if (isCandidateElement(node) && nodeNameEquals(node, QUALIFIER_ATTRIBUTE_ELEMENT)) { + Element attributeEle = (Element) node; + // 获取 key 属性 + String attributeName = attributeEle.getAttribute(KEY_ATTRIBUTE); + // 获取 value 属性 + String attributeValue = attributeEle.getAttribute(VALUE_ATTRIBUTE); + if (StringUtils.hasLength(attributeName) && StringUtils.hasLength(attributeValue)) { + // key value 属性映射 + BeanMetadataAttribute attribute = new BeanMetadataAttribute(attributeName, attributeValue); + attribute.setSource(extractSource(attributeEle)); + // 添加 qualifier 属性值 + qualifier.addMetadataAttribute(attribute); + } + else { + error("Qualifier 'attribute' tag must have a 'name' and 'value'", attributeEle); + return; + } + } + } + // 添加 qualifier + bd.addQualifier(qualifier); + } + finally { + this.parseState.pop(); + } +} +``` \ No newline at end of file