/* * Copyright 2002-2021 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * https://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.beans.factory.xml; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.Set; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.w3c.dom.Element; import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.springframework.beans.BeanMetadataAttribute; import org.springframework.beans.BeanMetadataAttributeAccessor; import org.springframework.beans.PropertyValue; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.BeanDefinitionHolder; import org.springframework.beans.factory.config.ConstructorArgumentValues; import org.springframework.beans.factory.config.RuntimeBeanNameReference; import org.springframework.beans.factory.config.RuntimeBeanReference; import org.springframework.beans.factory.config.TypedStringValue; import org.springframework.beans.factory.parsing.BeanEntry; import org.springframework.beans.factory.parsing.ConstructorArgumentEntry; import org.springframework.beans.factory.parsing.ParseState; import org.springframework.beans.factory.parsing.PropertyEntry; import org.springframework.beans.factory.parsing.QualifierEntry; import org.springframework.beans.factory.support.AbstractBeanDefinition; import org.springframework.beans.factory.support.AutowireCandidateQualifier; import org.springframework.beans.factory.support.BeanDefinitionDefaults; import org.springframework.beans.factory.support.BeanDefinitionReaderUtils; import org.springframework.beans.factory.support.LookupOverride; import org.springframework.beans.factory.support.ManagedArray; import org.springframework.beans.factory.support.ManagedList; import org.springframework.beans.factory.support.ManagedMap; import org.springframework.beans.factory.support.ManagedProperties; import org.springframework.beans.factory.support.ManagedSet; import org.springframework.beans.factory.support.MethodOverrides; import org.springframework.beans.factory.support.ReplaceOverride; import org.springframework.lang.Nullable; import org.springframework.util.Assert; import org.springframework.util.ClassUtils; import org.springframework.util.CollectionUtils; import org.springframework.util.ObjectUtils; import org.springframework.util.PatternMatchUtils; import org.springframework.util.StringUtils; import org.springframework.util.xml.DomUtils; /** * Stateful delegate class used to parse XML bean definitions. * Intended for use by both the main parser and any extension * {@link BeanDefinitionParser BeanDefinitionParsers} or * {@link BeanDefinitionDecorator BeanDefinitionDecorators}. * * @author Rob Harrop * @author Juergen Hoeller * @author Rod Johnson * @author Mark Fisher * @author Gary Russell * @since 2.0 * @see ParserContext * @see DefaultBeanDefinitionDocumentReader */ public class BeanDefinitionParserDelegate { public static final String BEANS_NAMESPACE_URI = "http://www.springframework.org/schema/beans"; public static final String MULTI_VALUE_ATTRIBUTE_DELIMITERS = ",; "; /** * Value of a T/F attribute that represents true. * Anything else represents false. */ public static final String TRUE_VALUE = "true"; public static final String FALSE_VALUE = "false"; /** * default-autowire 属性值之一: * 实际上是会优先执行constructor然后是byType */ public static final String DEFAULT_VALUE = "default"; /** * description元素必须在beans中的第一行,用于描述配置的信息 */ public static final String DESCRIPTION_ELEMENT = "description"; /** * default-autowire 属性值之一 默认属性值: * no:不启用自动注入 */ public static final String AUTOWIRE_NO_VALUE = "no"; /** * default-autowire 属性值之一: * 根据name注入 */ public static final String AUTOWIRE_BY_NAME_VALUE = "byName"; /** * default-autowire 属性值之一: * 这个是会根据类型去注入,当找到了会直接注入,没有找到不会报错, * 但是找到多个会报No unique bean of type的错误 */ public static final String AUTOWIRE_BY_TYPE_VALUE = "byType"; /** * default-autowire 属性值之一: * 这个是通过构造注入 */ public static final String AUTOWIRE_CONSTRUCTOR_VALUE = "constructor"; public static final String AUTOWIRE_AUTODETECT_VALUE = "autodetect"; /** * bean元素属性之一: * name标签是bean的名称标识,Ioc容器中bean的name标签不能重复,同一个bean中 * 可以与id重复(name值可以等于id值) * * property 设值注入性之一: * name 为类中要注入依赖项的名字。需要有set方法。name值与setXXX 中XXX一致,与声明的名字无关 */ public static final String NAME_ATTRIBUTE = "name"; public static final String BEAN_ELEMENT = "bean"; /** * property 设值注入性之一: * meta: 一个额外的属性,可以使用 BeanDefinition的getAttribute(key);方法获取, * * * */ public static final String META_ELEMENT = "meta"; /** * bean元素属性之一: * id标签是bean的唯一标识,Ioc容器中bean的id标签不能重复,否者报错 * * id标签的值 在 同一个配置文件中是惟一的, * 在多个spring文件中存在相同的id 或 name后面引入的配置会覆盖前面的bean */ public static final String ID_ATTRIBUTE = "id"; /** * bean属性之一: * spring中parent标签是指:某个的父类。这个类可以覆盖parent的属性 */ public static final String PARENT_ATTRIBUTE = "parent"; /** * class属性是bean常用属性,为bean的全限定类名,指向classpath下类定义所在位置 */ public static final String CLASS_ATTRIBUTE = "class"; /** * 使用abstract属性定义公共属性。bean使用abstract=true时,可以有class, * 也可以没有class,一般与parent配合使用 */ public static final String ABSTRACT_ATTRIBUTE = "abstract"; /** * bean元素属性之一: * 可以设置单例和多例: * singleton: 详见下方注释 * prototype:当前模式bean处于多例模式 * 原型,每次请求(每次使用)创建新的实例,destroy方式失效(因为没有用到的实例会被垃圾回收) * 不需要调用destory * 懒加载失效 */ public static final String SCOPE_ATTRIBUTE = "scope"; /** * 当前bean处在单例模式下(默认) * 指一个Bean容器中只存在一份 * 以单例模式创建的bean对象,在beans容器(IOC容器可以加载多个beans容器的配置文件) * 中的对象都是同一个内存地址对象 */ private static final String SINGLETON_ATTRIBUTE = "singleton"; /** 只有 true、false 用来指定bean是否在容器启动时初始化,为false时容器启动时初始化 * 用途: 通常用于解决spring循环引用的问题: */ public static final String LAZY_INIT_ATTRIBUTE = "lazy-init"; /** * autowire表示bean的自动装配 */ public static final String AUTOWIRE_ATTRIBUTE = "autowire"; /** * 值有 true, false、default 。autowire-candidate="false" 表示该对象不参与自动注入 */ public static final String AUTOWIRE_CANDIDATE_ATTRIBUTE = "autowire-candidate"; /** * primary的值有true和false两个可以选择。默认为false。当一个bean的primary设置为true,然后容器 * 中有多个与该bean相同类型的其他bean,此时,当使用@Autowired想要注入一个这个类型的bean时, * 就不会因为容器中存在多个该类型的bean而出现异常。而是优先使用primary为true的bean。不过, * 如果容器中不仅有多个该类型的bean,而且这些bean中有多个的primary的值设置为true, * 那么使用byType注入还是会出错 */ public static final String PRIMARY_ATTRIBUTE = "primary"; /** * depends-on适用于表面上看起来两个bean之间没有使用属性之类的强连接的bean,但是两个bean又确实 * 存在前后依赖关系的情况,被depends-on链接的bean 先创建,后销毁,依赖他人的bean是先于被依赖bean销毁的 */ public static final String DEPENDS_ON_ATTRIBUTE = "depends-on"; /** * bean元素属性之一: * init-method属性是bean的初始方法,在创建好bean后调用该方法 */ public static final String INIT_METHOD_ATTRIBUTE = "init-method"; public static final String DESTROY_METHOD_ATTRIBUTE = "destroy-method"; /** * bean元素属性之一: * factory-method工厂方法属性,通过该属性,我们可以调用一个指定的静态工厂方法,创建bean实例 */ public static final String FACTORY_METHOD_ATTRIBUTE = "factory-method"; /** * bean元素属性之一: * factory-bean就是生成bean的工厂对象,factory-bean和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"; /** * property 设值注入 * 通过setter对应的方法注入 。spring配置中property作为bean的属性。也就是指一个类中的成员。同时这个成员必须有set方法。 */ public static final String PROPERTY_ELEMENT = "property"; public static final String REF_ATTRIBUTE = "ref"; public static final String VALUE_ATTRIBUTE = "value"; /** * 方法的覆盖。注入bean的作用域小于当前bean时,希望每次可以拿到最新的注入bean。 */ public static final String LOOKUP_METHOD_ELEMENT = "lookup-method"; /** * 方法的替换 ,要实现spring的MethodReplacer接口 */ 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"; /** * property 设值注入 之一: * ref 为引用项bean的id 或name 。value 值为值类型 * 就是找当前配置文件里的bean , * 是寻找全局(可以到其他xml中)中的 bean; * 标签里有3种属性 * , * , * 。 * 在4.0BeanXSD中 ref 元素上的local 属性不再受支持 */ public static final String REF_ELEMENT = "ref"; /** * idref: idref元素只是一种防止错误的方法,可以将容器中另一个bean的id(一个字符串值,而不是引用)传递给一个 * 元素(在某种意义上等同于) * * * * * * * */ public static final String IDREF_ELEMENT = "idref"; /** * property 设值注入 之一: * bean: 内部 Bean:当 Spring IoC 容器中的 bean1 只会被 bean2 引用,而不会被容器中任何其他 Bean 引用的时候,则可以将这个 bean1 以内部 Bean 的方式注入到 bean2 中。 */ public static final String BEAN_REF_ATTRIBUTE = "bean"; public static final String PARENT_REF_ATTRIBUTE = "parent"; /** * property 设值注入 之一: * value: 为属性注入字面值 */ public static final String VALUE_ELEMENT = "value"; public static final String NULL_ELEMENT = "null"; /** * property 设值注入 之一: * array:当属性为 java.util.Array 的时候 可以在集合上加 merge="true",允许与父类集合合并(继承的概念) * * * 足球 * 篮球 * 排球 * * */ public static final String ARRAY_ELEMENT = "array"; /** * property 设值注入 之一: * list: 当属性为 java.util.List 的时候,可以在集合上加 merge="true",允许与父类集合合并 * * * * * 唱歌 * 运动 * 读书 * * * */ public static final String LIST_ELEMENT = "list"; /** * property 设值注入 之一: * set: 当属性为 java.util.Set 的时候 可以在集合上加 merge="true",允许与父类集合合并 * * * * 唱歌 * 运动 * 读书 * * * */ public static final String SET_ELEMENT = "set"; /** * property 设值注入 之一: * map: 当属性为 java.util.Map 的时候 可以在集合上加 merge="true",允许与父类集合合并 * * * * * * key01 * 唱歌 * * * key02 * 运动 * * * * * * * * */ 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"; /** * property 设值注入 之一: * props: 当属性为 java.util.Properties 的时候 可以在集合上加 merge="true",允许与父类集合合并 * * * * * 唱歌 * 运动 * 读书 * * * * */ public static final String PROPS_ELEMENT = "props"; public static final String PROP_ELEMENT = "prop"; public static final String MERGE_ATTRIBUTE = "merge"; /** * 当bean的注入项有多个实现时,使用Qualifier指定要注入的bean的标识 */ public static final String QUALIFIER_ELEMENT = "qualifier"; public static final String QUALIFIER_ATTRIBUTE_ELEMENT = "attribute"; /** 全局懒加载 作用于beans 身上 * spring 配置默认default-lazy-init为false,当属性default-lazy-init设置成true时, * spring不会再去加载整个对象的实例图,大大减少了初始化的时间,减少spring的启动时间 */ public static final String DEFAULT_LAZY_INIT_ATTRIBUTE = "default-lazy-init"; /** * 从spring2.0M2开始,beans支持default-merge=”true“ * 子类不需要重新定义父类的List型属性中已定义过的内容 */ public static final String DEFAULT_MERGE_ATTRIBUTE = "default-merge"; /** * bean 注入属性方式总体来看有五个值: * no、default、byType、byName、constructor */ public static final String DEFAULT_AUTOWIRE_ATTRIBUTE = "default-autowire"; /** * 候选者属性,自动装配时既匹配则被包含。不匹配的排除在外。 * 此属性的值允许使用模式字符串,例如我们制定default-autowire-candidates='abc', * 则所有以‘abc’结尾的Bean都将被自己装配。他还支持多个字符串,可以通过空格等分割。 */ public static final String DEFAULT_AUTOWIRE_CANDIDATES_ATTRIBUTE = "default-autowire-candidates"; /** * default-init-method="init" * 很多Bean都需要配置初始化方法和销毁方法,那么可以在beans标签中配置default-init-method和 * default-destroy-method来指定所有Bean的默认初始化方法和销毁方法(init和下方的destroy是 * bean中的方法) */ public static final String DEFAULT_INIT_METHOD_ATTRIBUTE = "default-init-method"; /** * default-destroy-method="destroy" */ public static final String DEFAULT_DESTROY_METHOD_ATTRIBUTE = "default-destroy-method"; protected final Log logger = LogFactory.getLog(getClass()); private final XmlReaderContext readerContext; private final DocumentDefaultsDefinition defaults = new DocumentDefaultsDefinition(); private final ParseState parseState = new ParseState(); /** * Stores all used bean names so we can enforce uniqueness on a per * beans-element basis. Duplicate bean ids/names may not exist within the * same level of beans element nesting, but may be duplicated across levels. */ private final Set usedNames = new HashSet<>(); /** * Create a new BeanDefinitionParserDelegate associated with the supplied * {@link XmlReaderContext}. */ public BeanDefinitionParserDelegate(XmlReaderContext readerContext) { Assert.notNull(readerContext, "XmlReaderContext must not be null"); this.readerContext = readerContext; } /** * Get the {@link XmlReaderContext} associated with this helper instance. */ public final XmlReaderContext getReaderContext() { return this.readerContext; } /** * Invoke the {@link org.springframework.beans.factory.parsing.SourceExtractor} * to pull the source metadata from the supplied {@link Element}. */ @Nullable protected Object extractSource(Element ele) { return this.readerContext.extractSource(ele); } /** * Report an error with the given message for the given source element. */ protected void error(String message, Node source) { this.readerContext.error(message, source, this.parseState.snapshot()); } /** * Report an error with the given message for the given source element. */ protected void error(String message, Element source) { this.readerContext.error(message, source, this.parseState.snapshot()); } /** * Report an error with the given message for the given source element. */ protected void error(String message, Element source, Throwable cause) { this.readerContext.error(message, source, this.parseState.snapshot(), cause); } /** * Initialize the default settings assuming a {@code null} parent delegate. */ public void initDefaults(Element root) { initDefaults(root, null); } /** * Initialize the default lazy-init, autowire, dependency check settings, * init-method, destroy-method and merge settings. Support nested 'beans' * element use cases by falling back to the given parent in case the * defaults are not explicitly set locally. * @see #populateDefaults(DocumentDefaultsDefinition, DocumentDefaultsDefinition, org.w3c.dom.Element) * @see #getDefaults() */ public void initDefaults(Element root, @Nullable BeanDefinitionParserDelegate parent) { populateDefaults(this.defaults, (parent != null ? parent.defaults : null), root); this.readerContext.fireDefaultsRegistered(this.defaults); System.out.println("最后将默认的DocumentDefaultsDefinition,存放(注册)到List "); } /** * Populate the given DocumentDefaultsDefinition instance with the default lazy-init, * autowire, dependency check settings, init-method, destroy-method and merge settings. * Support nested 'beans' element use cases by falling back to {@code parentDefaults} * in case the defaults are not explicitly set locally. * @param defaults the defaults to populate * @param parentDefaults the parent BeanDefinitionParserDelegate (if any) defaults to fall back to * @param root the root element of the current bean definition document (or nested beans element) * * 使用默认的惰性初始化、自动装配、依赖性检查设置、初始化方法、销毁方法和合并设置填充给定的 DocumentDefaultsDefinition 实例。 * 通过回退到 parentDefaults} 来支持嵌套的“bean”元素用例,以防默认值未在本地显式设置。 * @param defaults 默认默认填充 * @param parentDefaults 父 BeanDefinitionParserDelegate(如果有) 默认回退 * @param root 当前 bean 定义文档的根元素(或嵌套 beans 元素) */ protected void populateDefaults(DocumentDefaultsDefinition defaults, @Nullable DocumentDefaultsDefinition parentDefaults, Element root) { // 是否进行懒加载 System.err.println("委托类解析 BeanDefinitionParserDelegate.populateDefaults解析xml"); String lazyInit = root.getAttribute(DEFAULT_LAZY_INIT_ATTRIBUTE); System.out.println("注这里一共3个;一个为默认类型,一个当前类,一个父类"); System.out.println("需设置默认类型 - 检查当前的懒加载为:" + lazyInit + " 如果当前类手动设置了其模式会向上委托,保持与父类一致"); if (isDefaultValue(lazyInit)) { // Potentially inherited from outer sections, otherwise falling back to false. lazyInit = (parentDefaults != null ? parentDefaults.getLazyInit() : FALSE_VALUE); } defaults.setLazyInit(lazyInit); System.err.println("当前的beans是否进行懒加载" + DEFAULT_LAZY_INIT_ATTRIBUTE + ":" + 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); System.err.println("子类不需要重新定义父类的List型属性中已定义过的内容" + DEFAULT_MERGE_ATTRIBUTE + ":" + 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)); System.err.println("所有以此属性结尾的都会被自动装配:" + DEFAULT_AUTOWIRE_CANDIDATES_ATTRIBUTE + ":" + autowire); } else if (parentDefaults != null) { defaults.setAutowireCandidates(parentDefaults.getAutowireCandidates()); System.err.println("所有以此属性结尾的都会被自动装配" + ":" + parentDefaults.getAutowireCandidates()); } if (root.hasAttribute(DEFAULT_INIT_METHOD_ATTRIBUTE)) { defaults.setInitMethod(root.getAttribute(DEFAULT_INIT_METHOD_ATTRIBUTE)); System.err.println("初始化方法为:" + root.getAttribute(DEFAULT_INIT_METHOD_ATTRIBUTE)); } else if (parentDefaults != null) { defaults.setInitMethod(parentDefaults.getInitMethod()); System.err.println("初始化方法为:" + parentDefaults.getInitMethod()); } if (root.hasAttribute(DEFAULT_DESTROY_METHOD_ATTRIBUTE)) { defaults.setDestroyMethod(root.getAttribute(DEFAULT_DESTROY_METHOD_ATTRIBUTE)); System.err.println("销毁方法为:" + root.getAttribute(DEFAULT_DESTROY_METHOD_ATTRIBUTE)); } else if (parentDefaults != null) { defaults.setDestroyMethod(parentDefaults.getDestroyMethod()); System.err.println("销毁方法为:" + parentDefaults.getDestroyMethod()); } defaults.setSource(this.readerContext.extractSource(root)); } /** * Return the defaults definition object. */ public DocumentDefaultsDefinition getDefaults() { return this.defaults; } /** * Return the default settings for bean definitions as indicated within * the attributes of the top-level {@code } element. */ public BeanDefinitionDefaults getBeanDefinitionDefaults() { BeanDefinitionDefaults bdd = new BeanDefinitionDefaults(); bdd.setLazyInit(TRUE_VALUE.equalsIgnoreCase(this.defaults.getLazyInit())); bdd.setAutowireMode(getAutowireMode(DEFAULT_VALUE)); bdd.setInitMethodName(this.defaults.getInitMethod()); bdd.setDestroyMethodName(this.defaults.getDestroyMethod()); return bdd; } /** * Return any patterns provided in the 'default-autowire-candidates' * attribute of the top-level {@code } element. */ @Nullable public String[] getAutowireCandidatePatterns() { String candidatePattern = this.defaults.getAutowireCandidates(); return (candidatePattern != null ? StringUtils.commaDelimitedListToStringArray(candidatePattern) : null); } /** * Parses the supplied {@code } element. May return {@code null} * if there were errors during parse. Errors are reported to the * {@link org.springframework.beans.factory.parsing.ProblemReporter}. */ @Nullable public BeanDefinitionHolder parseBeanDefinitionElement(Element ele) { return parseBeanDefinitionElement(ele, null); } /** * Parses the supplied {@code } element. May return {@code null} * if there were errors during parse. Errors are reported to the * {@link org.springframework.beans.factory.parsing.ProblemReporter}. * * 1.提取元素中的id以及name属性。 * 2.进一步解析其他所有属性并统一封装至GenericBeanDefinition类型的实例中。 * 3.如果检测bean没有指定beanName,那么使用默认规则为此Bean生成BeanName(beanId). * 4.将获得到的信息封装到BeanDefinitionHolder的实例中。 */ @Nullable public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) { System.out.println("1.提取元素中的id以及name属性。"); System.out.println("2.进一步解析其他所有属性并统一封装至GenericBeanDefinition类型的实例中。"); System.out.println("3.如果检测bean没有指定beanName,那么使用默认规则为此Bean生成BeanName(beanId)."); System.out.println("4.将获得到的信息封装到BeanDefinitionHolder的实例中。"); System.err.println("解析:BeanDefinition"); // 解析id属性 String id = ele.getAttribute(ID_ATTRIBUTE); System.err.println("获取当前bean的id:" + id); // 解析name属性 String nameAttr = ele.getAttribute(NAME_ATTRIBUTE); System.err.println("获取name属性数组的方式:" + nameAttr); // 分割name属性 得到别名的集合 List aliases = new ArrayList<>(); if (StringUtils.hasLength(nameAttr)) { String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS); aliases.addAll(Arrays.asList(nameArr)); System.err.println("设置aliases"); } 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"); } } System.err.println("获取当前bean的name:" + beanName); if (containingBean == null) { checkNameUniqueness(beanName, aliases, ele); } System.out.println("AbstractBeanDefinition --- parseBeanDefinitionElement解析"); 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); } return null; } /** * Validate that the specified bean name and aliases have not been used already * within the current level of beans element nesting. */ protected void checkNameUniqueness(String beanName, List aliases, Element beanElement) { String foundName = null; 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); } /** * Parse the bean definition itself, without regard to name or aliases. May return * {@code null} if problems occurred during the parsing of the bean definition. */ @Nullable public AbstractBeanDefinition parseBeanDefinitionElement( Element ele, String beanName, @Nullable BeanDefinition containingBean) { this.parseState.push(new BeanEntry(beanName)); String className = null; if (ele.hasAttribute(CLASS_ATTRIBUTE)) { className = ele.getAttribute(CLASS_ATTRIBUTE).trim(); System.err.println("获取当前的className:" + className); } String parent = null; if (ele.hasAttribute(PARENT_ATTRIBUTE)) { parent = ele.getAttribute(PARENT_ATTRIBUTE); System.err.println("获取当前bean的:parent:" + parent); } try { /** 创建用于承载属性的AbstractBeanDefinition类型的GenericBeanDefinition*/ System.out.println("创建用于承载属性的AbstractBeanDefinition类型的GenericBeanDefinition"); AbstractBeanDefinition bd = createBeanDefinition(className, parent); /** 硬编码解析bean的给种属性*/ System.out.println("parseBeanDefinitionAttributes 硬编码解析bean的给种属性"); parseBeanDefinitionAttributes(ele, beanName, containingBean, bd); System.out.println("AbstractBeanDefinition:" + bd.toString()); /** 提取description*/ System.out.println("提取description"); bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT)); /** 解析元数据*/ System.out.println("解析元数据"); parseMetaElements(ele, bd); /** 解析lookup-method 属性*/ System.out.println("解析lookup-method 属性"); parseLookupOverrideSubElements(ele, bd.getMethodOverrides()); /** 解析replaced-method 属性*/ System.out.println("解析replaced-method 属性"); parseReplacedMethodSubElements(ele, bd.getMethodOverrides()); /** 解析构造函数参数*/ System.out.println("解析构造函数参数"); parseConstructorArgElements(ele, bd); /** 解析property子元素*/ System.out.println("解析property子元素"); parsePropertyElements(ele, bd); /** 解析qualifier子元素*/ System.out.println("解析qualifier子元素"); parseQualifierElements(ele, bd); bd.setResource(this.readerContext.getResource()); bd.setSource(extractSource(ele)); System.out.println("AbstractBeanDefinition:" + bd.toString()); 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; } /** * Apply the attributes of the given bean element to the given bean * definition. * @param ele bean declaration element * @param beanName bean name * @param containingBean containing bean definition * @return a bean definition initialized according to the bean element attributes */ public AbstractBeanDefinition parseBeanDefinitionAttributes(Element ele, String beanName, @Nullable BeanDefinition containingBean, AbstractBeanDefinition bd) { //如果设置singleton直接报错 因为升级成了scope属性 System.err.println("如果设置singleton直接报错 因为升级成了scope属性"); 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)) { bd.setScope(ele.getAttribute(SCOPE_ATTRIBUTE)); System.err.println("parseBeanDefinitionAttributes 解析scope属性:" + ele.getAttribute(SCOPE_ATTRIBUTE)); } else if (containingBean != null) { // Take default from containing bean in case of an inner bean definition. bd.setScope(containingBean.getScope()); System.err.println("parseBeanDefinitionAttributes 解析scope属性 在嵌入beanDifinition情况下且没有单独指定 scope 属性则佼用父类默认的属性:" + 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)); System.err.println("解析lazy-init属性:" + bd.getLazyInit()); String autowire = ele.getAttribute(AUTOWIRE_ATTRIBUTE); bd.setAutowireMode(getAutowireMode(autowire)); System.err.println("解析autowire属性:" + getAutowireMode(autowire)); if (ele.hasAttribute(DEPENDS_ON_ATTRIBUTE)) { String dependsOn = ele.getAttribute(DEPENDS_ON_ATTRIBUTE); bd.setDependsOn(StringUtils.tokenizeToStringArray(dependsOn, MULTI_VALUE_ATTRIBUTE_DELIMITERS)); System.err.println("解析dependsOn属性:" + bd.getDescription()); } 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)); } System.err.println("解析autowireCandidate属性:" + TRUE_VALUE.equals(autowireCandidate)); if (ele.hasAttribute(PRIMARY_ATTRIBUTE)) { bd.setPrimary(TRUE_VALUE.equals(ele.getAttribute(PRIMARY_ATTRIBUTE))); System.err.println("解析primary属性:" + TRUE_VALUE.equals(ele.getAttribute(PRIMARY_ATTRIBUTE))); } if (ele.hasAttribute(INIT_METHOD_ATTRIBUTE)) { String initMethodName = ele.getAttribute(INIT_METHOD_ATTRIBUTE); bd.setInitMethodName(initMethodName); System.err.println("解析initMethodName属性:" + initMethodName); } else if (this.defaults.getInitMethod() != null) { bd.setInitMethodName(this.defaults.getInitMethod()); bd.setEnforceInitMethod(false); System.err.println("解析initMethodName属性:" + this.defaults.getInitMethod()); } if (ele.hasAttribute(DESTROY_METHOD_ATTRIBUTE)) { String destroyMethodName = ele.getAttribute(DESTROY_METHOD_ATTRIBUTE); bd.setDestroyMethodName(destroyMethodName); System.err.println("解析destroyMethodName属性:" + destroyMethodName); } else if (this.defaults.getDestroyMethod() != null) { bd.setDestroyMethodName(this.defaults.getDestroyMethod()); bd.setEnforceDestroyMethod(false); System.err.println("解析destroyMethodName属性:" + this.defaults.getDestroyMethod()); } if (ele.hasAttribute(FACTORY_METHOD_ATTRIBUTE)) { bd.setFactoryMethodName(ele.getAttribute(FACTORY_METHOD_ATTRIBUTE)); System.err.println("解析factoryMethodName属性:" + bd.getFactoryMethodName()); } if (ele.hasAttribute(FACTORY_BEAN_ATTRIBUTE)) { bd.setFactoryBeanName(ele.getAttribute(FACTORY_BEAN_ATTRIBUTE)); System.err.println("解析factoryBeanName属性:" + bd.getFactoryBeanName()); } return bd; } /** * Create a bean definition for the given class name and parent name. * @param className the name of the bean class * @param parentName the name of the bean's parent bean * @return the newly created bean definition * @throws ClassNotFoundException if bean class resolution was attempted but failed */ protected AbstractBeanDefinition createBeanDefinition(@Nullable String className, @Nullable String parentName) throws ClassNotFoundException { return BeanDefinitionReaderUtils.createBeanDefinition( parentName, className, this.readerContext.getBeanClassLoader()); } /** * 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); /** 提取meta*/ System.out.println("获取当前的节点:" + node.toString()); if (isCandidateElement(node) && nodeNameEquals(node, META_ELEMENT)) { Element metaElement = (Element) node; String key = metaElement.getAttribute(KEY_ATTRIBUTE); String value = metaElement.getAttribute(VALUE_ATTRIBUTE); System.err.println("获取当前meta标签的key:" + key); System.err.println("获取当前meta标签的value:" + value); /** 使用key、value构造 BeanMetadataAttribute*/ BeanMetadataAttribute attribute = new BeanMetadataAttribute(key, value); attribute.setSource(extractSource(metaElement)); /** 记录信息*/ attributeAccessor.addMetadataAttribute(attribute); System.out.println("记录信息"); System.out.println("使用key、value构造 BeanMetadataAttribute:" + attribute.toString()); } } } /** * Parse the given autowire attribute value into * {@link AbstractBeanDefinition} autowire constants. */ @SuppressWarnings("deprecation") public int getAutowireMode(String attrValue) { String attr = attrValue; if (isDefaultValue(attr)) { attr = this.defaults.getAutowire(); } int autowire = AbstractBeanDefinition.AUTOWIRE_NO; if (AUTOWIRE_BY_NAME_VALUE.equals(attr)) { autowire = AbstractBeanDefinition.AUTOWIRE_BY_NAME; } else if (AUTOWIRE_BY_TYPE_VALUE.equals(attr)) { autowire = AbstractBeanDefinition.AUTOWIRE_BY_TYPE; } else if (AUTOWIRE_CONSTRUCTOR_VALUE.equals(attr)) { autowire = AbstractBeanDefinition.AUTOWIRE_CONSTRUCTOR; } else if (AUTOWIRE_AUTODETECT_VALUE.equals(attr)) { autowire = AbstractBeanDefinition.AUTOWIRE_AUTODETECT; } // Else leave default value. return autowire; } /** * Parse constructor-arg sub-elements of the given bean element. */ 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); } } } /** * Parse property sub-elements of the given bean element. */ 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); } } } /** * Parse qualifier sub-elements of the given bean element. */ 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); } } } /** * 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); /** 仅当在spring默认bean的子元素下切为 lookup-method时 有效*/ if (isCandidateElement(node) && nodeNameEquals(node, LOOKUP_METHOD_ELEMENT)) { Element ele = (Element) node; /** 获取要修饰的方法*/ String methodName = ele.getAttribute(NAME_ATTRIBUTE); System.err.println("lookup-method下的方法名称" + methodName); /** 获取配置返回的bean*/ String beanRef = ele.getAttribute(BEAN_ELEMENT); System.err.println("lookup-method下的bean指向" + beanRef); System.err.println("使用LookupOverride类型的实体类来进行数据承载并记录在AbstractBeanDefinition中的methodOverrides属性中"); LookupOverride override = new LookupOverride(methodName, beanRef); override.setSource(extractSource(ele)); overrides.addOverride(override); } } } /** * 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); /** 仅当在spring默认bean的子元素下切为 replaced-method时 有效*/ if (isCandidateElement(node) && nodeNameEquals(node, REPLACED_METHOD_ELEMENT)) { Element replacedMethodEle = (Element) node; /** 提取要替换的据方法*/ String name = replacedMethodEle.getAttribute(NAME_ATTRIBUTE); System.err.println("replaced-method 替换方法的名称为:" + name); /** 提取对应的新的替换方法*/ String callback = replacedMethodEle.getAttribute(REPLACER_ATTRIBUTE); System.err.println("replaced-method 替换新的方法的名称的引用" + callback); 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); System.err.println("replaced-method 记录参数" + match); match = (StringUtils.hasText(match) ? match : DomUtils.getTextValue(argTypeEle)); if (StringUtils.hasText(match)) { replaceOverride.addTypeIdentifier(match); } } System.err.println("使用replaceOverride类型的实体类来进行数据承载并记录在AbstractBeanDefinition中的methodOverrides属性中"); replaceOverride.setSource(extractSource(replacedMethodEle)); overrides.addOverride(replaceOverride); } } } /** * Parse a constructor-arg element. * * 如果配置文件中指定了index属性,那么操作步骤如下 * 1.解析constructor-arg的子元素 * 2.使用ConstructorArgumentValues.ValueHolder类型来封装解析出来的元素 * 3.将type、name和index属性一并封装在ConstructorArgumentValues.ValueHolder类型中 * 并添加至当前BeanDefinition的ConstructorArgumentValues的IndexedArgumentValues属性中 * 如果没有指定index属性,那么操作步骤如下 * 1.解析constructor-arg的子元素 * 2.使用ConstructorArgumentValues.ValueHolder类型来封装解析出来的元素 * 3.将type、name和index属性一并封装在ConstructorArgumentValues.ValueHolder类型中 * 并添加至当前BeanDefinition的ConstructorArgumentValues的GenericArgumentValue属性中 */ public void parseConstructorArgElement(Element ele, BeanDefinition bd) { String indexAttr = ele.getAttribute(INDEX_ATTRIBUTE); System.err.println("constructor-arg 的index属性:" + indexAttr); String typeAttr = ele.getAttribute(TYPE_ATTRIBUTE); System.err.println("constructor-arg 的type属性:" + typeAttr); String nameAttr = ele.getAttribute(NAME_ATTRIBUTE); System.err.println("constructor-arg 的name属性:" + nameAttr); 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(index)); //解析 ele 对应的罚性元素 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 { System.err.println("constructor-arg-ConstructorArgumentValues.IndexedArgumentValue:" + valueHolder.toString()); 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 { try { /** 没有index属性则忽略去属性,自动寻找*/ 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)); System.err.println("constructor-arg-ConstructorArgumentValues.GenericArgumentValue:" + valueHolder.toString()); bd.getConstructorArgumentValues().addGenericArgumentValue(valueHolder); } finally { this.parseState.pop(); } } } /** * Parse a property element. */ public void parsePropertyElement(Element ele, BeanDefinition bd) { /** 获取元素中的name值*/ 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); PropertyValue pv = new PropertyValue(propertyName, val); parseMetaElements(ele, pv); pv.setSource(extractSource(ele)); bd.getPropertyValues().addPropertyValue(pv); } finally { this.parseState.pop(); } } /** * 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; } 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; String attributeName = attributeEle.getAttribute(KEY_ATTRIBUTE); String attributeValue = attributeEle.getAttribute(VALUE_ATTRIBUTE); if (StringUtils.hasLength(attributeName) && StringUtils.hasLength(attributeValue)) { 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(); } } /** * Get the value of a property element. May be a list etc. * Also used for constructor arguments, "propertyName" being null in this case. * * 1.略过description或者meta * 2.提取constructor-arg上的ref和value属性,以便于根据规则验证正确性其规则在constructor-arg上不存在以下情况 * 同时既有ref属性又有value属性 * 存在ref属性或者value属性又有子元素 * 3.ref属性的处理。使用RuntimeBeanReference封装对应的ref名称,如: * * 4.value属性的处理。使用TypedStringValue封装,如: * * 5.子元素的处理,如: * * * * * */ @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. * 一个属性只能对应一种类型,ref、value、list等。 */ NodeList nl = ele.getChildNodes(); Element subElement = null; for (int i = 0; i < nl.getLength(); i++) { Node node = nl.item(i); /** 对应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; } } } /** * 解析constructor-arg上的ref属性 */ boolean hasRefAttribute = ele.hasAttribute(REF_ATTRIBUTE); /** * 解析constructor-arg上的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); /** * 在constructor-arg上不存在 * 1.同时既有ref属性又有value属性 * 2.存在ref属性或者value属性又有子元素 */ } if (hasRefAttribute) { // ref属性处理,使用RuntimeBeanReference封装的ref名称 String refName = ele.getAttribute(REF_ATTRIBUTE); System.err.println("constructor-arg 的refName:" + refName); if (!StringUtils.hasText(refName)) { error(elementName + " contains empty 'ref' attribute", ele); } RuntimeBeanReference ref = new RuntimeBeanReference(refName); System.err.println("将当前的refName 封装成 RuntimeBeanReference:" + ref.toString()); ref.setSource(extractSource(ele)); return ref; } else if (hasValueAttribute) { /** value 属性处理,使用TypeStringValue封装*/ TypedStringValue valueHolder = new TypedStringValue(ele.getAttribute(VALUE_ATTRIBUTE)); valueHolder.setSource(extractSource(ele)); System.err.println("将当前的value 封装成TypedStringValue:" + ele.getAttribute(VALUE_ATTRIBUTE)); return valueHolder; } else if (subElement != null) { /** 解析子元素*/ return parsePropertySubElement(subElement, bd); } else { /** 既没有ref 也没有 value spring蒙圈了 直接报错*/ // Neither child element nor "ref" or "value" attribute found. error(elementName + " must specify a ref or value", ele); return null; } } /** * Parse a value, ref or collection sub-element of a property or * constructor-arg element. * @param ele subelement of property element; we don't know which yet * @param bd the current bean definition (if any) */ @Nullable public Object parsePropertySubElement(Element ele, @Nullable BeanDefinition bd) { return parsePropertySubElement(ele, bd, null); } /** * Parse a value, ref or collection sub-element of a property or * constructor-arg element. * @param ele subelement of property element; we don't know which yet * @param bd the current bean definition (if any) * @param defaultValueType the default type (class name) for any * {@code } tag that might be created */ @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)) { BeanDefinitionHolder nestedBd = parseBeanDefinitionElement(ele, bd); if (nestedBd != null) { nestedBd = decorateBeanDefinitionIfRequired(ele, nestedBd, bd); } return nestedBd; } else if (nodeNameEquals(ele, REF_ELEMENT)) { // A generic reference to any name of any bean. /** 解析local*/ 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; } RuntimeBeanReference ref = new RuntimeBeanReference(refName, toParent); ref.setSource(extractSource(ele)); return ref; } /** 对idref子元素解析*/ else if (nodeNameEquals(ele, IDREF_ELEMENT)) { return parseIdRefElement(ele); } /** 对value子元素解析*/ else if (nodeNameEquals(ele, VALUE_ELEMENT)) { return parseValueElement(ele, defaultValueType); } /** 对null子元素进行解析*/ 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; } /** 解析array子元素*/ else if (nodeNameEquals(ele, ARRAY_ELEMENT)) { return parseArrayElement(ele, bd); } /** 解析list子元素*/ else if (nodeNameEquals(ele, LIST_ELEMENT)) { return parseListElement(ele, bd); } /** 解析set子元素*/ else if (nodeNameEquals(ele, SET_ELEMENT)) { return parseSetElement(ele, bd); } /** 解析map子元素*/ else if (nodeNameEquals(ele, MAP_ELEMENT)) { return parseMapElement(ele, bd); } /** 解析props子元素*/ else if (nodeNameEquals(ele, PROPS_ELEMENT)) { return parsePropsElement(ele); } else { error("Unknown property sub-element: [" + ele.getNodeName() + "]", ele); return null; } } /** * Return a typed String value Object for the given 'idref' element. */ @Nullable public Object parseIdRefElement(Element ele) { // A generic reference to any name of any 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; } RuntimeBeanNameReference ref = new RuntimeBeanNameReference(refName); ref.setSource(extractSource(ele)); return ref; } /** * Return a typed String value Object for the given value element. */ public Object parseValueElement(Element ele, @Nullable String defaultTypeName) { // It's a literal value. String value = DomUtils.getTextValue(ele); 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; } } /** * Build a typed String value Object for the given raw value. * @see org.springframework.beans.factory.config.TypedStringValue */ protected TypedStringValue buildTypedStringValue(String value, @Nullable String targetTypeName) throws ClassNotFoundException { 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; } /** * Parse an array element. */ public Object parseArrayElement(Element arrayEle, @Nullable BeanDefinition bd) { String elementType = arrayEle.getAttribute(VALUE_TYPE_ATTRIBUTE); NodeList nl = arrayEle.getChildNodes(); ManagedArray target = new ManagedArray(elementType, nl.getLength()); target.setSource(extractSource(arrayEle)); target.setElementTypeName(elementType); target.setMergeEnabled(parseMergeAttribute(arrayEle)); parseCollectionElements(nl, target, bd, elementType); return target; } /** * Parse a list element. */ 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; } /** * Parse a set element. */ 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; } 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)); } } } /** * Parse a map element. */ public Map parseMapElement(Element mapEle, @Nullable BeanDefinition bd) { String defaultKeyType = mapEle.getAttribute(KEY_TYPE_ATTRIBUTE); String defaultValueType = mapEle.getAttribute(VALUE_TYPE_ATTRIBUTE); List entryEles = DomUtils.getChildElementsByTagName(mapEle, ENTRY_ELEMENT); ManagedMap map = new ManagedMap<>(entryEles.size()); map.setSource(extractSource(mapEle)); map.setKeyTypeName(defaultKeyType); map.setValueTypeName(defaultValueType); map.setMergeEnabled(parseMergeAttribute(mapEle)); 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 candidateEle) { 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; boolean hasKeyAttribute = entryEle.hasAttribute(KEY_ATTRIBUTE); 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) { key = buildTypedStringValueForMap(entryEle.getAttribute(KEY_ATTRIBUTE), defaultKeyType, entryEle); } else if (hasKeyRefAttribute) { String refName = entryEle.getAttribute(KEY_REF_ATTRIBUTE); if (!StringUtils.hasText(refName)) { error(" element contains empty 'key-ref' attribute", entryEle); } RuntimeBeanReference ref = new RuntimeBeanReference(refName); ref.setSource(extractSource(entryEle)); key = ref; } else if (keyEle != null) { key = parseKeyElement(keyEle, bd, defaultKeyType); } else { error(" element must specify a key", entryEle); } // Extract value from attribute or sub-element. Object value = null; boolean hasValueAttribute = entryEle.hasAttribute(VALUE_ATTRIBUTE); boolean hasValueRefAttribute = entryEle.hasAttribute(VALUE_REF_ATTRIBUTE); 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) { String valueType = entryEle.getAttribute(VALUE_TYPE_ATTRIBUTE); if (!StringUtils.hasText(valueType)) { valueType = defaultValueType; } value = buildTypedStringValueForMap(entryEle.getAttribute(VALUE_ATTRIBUTE), valueType, entryEle); } else if (hasValueRefAttribute) { String refName = entryEle.getAttribute(VALUE_REF_ATTRIBUTE); if (!StringUtils.hasText(refName)) { error(" element contains empty 'value-ref' attribute", entryEle); } 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; } /** * Build a typed String value Object for the given raw value. * @see org.springframework.beans.factory.config.TypedStringValue */ protected final Object buildTypedStringValueForMap(String value, String defaultTypeName, Element entryEle) { try { TypedStringValue typedValue = buildTypedStringValue(value, defaultTypeName); typedValue.setSource(extractSource(entryEle)); return typedValue; } catch (ClassNotFoundException ex) { error("Type class [" + defaultTypeName + "] not found for Map key/value type", entryEle, ex); return value; } } /** * Parse a key sub-element of a map element. */ @Nullable protected Object parseKeyElement(Element keyEle, @Nullable BeanDefinition bd, String defaultKeyTypeName) { NodeList nl = keyEle.getChildNodes(); Element subElement = null; for (int i = 0; i < nl.getLength(); i++) { Node node = nl.item(i); if (node instanceof Element) { // Child element is what we're looking for. if (subElement != null) { error(" element must not contain more than one value sub-element", keyEle); } else { subElement = (Element) node; } } } if (subElement == null) { return null; } return parsePropertySubElement(subElement, bd, defaultKeyTypeName); } /** * Parse a props element. */ public Properties parsePropsElement(Element propsEle) { ManagedProperties props = new ManagedProperties(); props.setSource(extractSource(propsEle)); props.setMergeEnabled(parseMergeAttribute(propsEle)); List propEles = DomUtils.getChildElementsByTagName(propsEle, PROP_ELEMENT); for (Element propEle : propEles) { String key = propEle.getAttribute(KEY_ATTRIBUTE); // Trim the text value to avoid unwanted whitespace // caused by typical XML formatting. String value = DomUtils.getTextValue(propEle).trim(); TypedStringValue keyHolder = new TypedStringValue(key); keyHolder.setSource(extractSource(propEle)); TypedStringValue valueHolder = new TypedStringValue(value); valueHolder.setSource(extractSource(propEle)); props.put(keyHolder, valueHolder); } return props; } /** * Parse the merge attribute of a collection element, if any. */ public boolean parseMergeAttribute(Element collectionElement) { String value = collectionElement.getAttribute(MERGE_ATTRIBUTE); if (isDefaultValue(value)) { value = this.defaults.getMerge(); } return TRUE_VALUE.equals(value); } /** * Parse a custom element (outside of the default namespace). * @param ele the element to parse * @return the resulting bean definition */ @Nullable public BeanDefinition parseCustomElement(Element ele) { return parseCustomElement(ele, null); } /** * Parse a custom element (outside of the default namespace). * @param ele the element to parse * @param containingBd the containing bean definition (if any) * @return the resulting bean definition * * containingBd 为父类bean,对顶层元素的解析应设置为null */ @Nullable public BeanDefinition parseCustomElement(Element ele, @Nullable BeanDefinition containingBd) { System.out.println("==================处理自定义bean====================="); String namespaceUri = getNamespaceURI(ele); System.err.println("获取对应的命名空间:" + namespaceUri); if (namespaceUri == null) { return null; } /** 根据命名空间找到对应的NamespaceHandler*/ NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri); System.err.println("根据命名空间找到对应的NamespaceHandler" + handler.toString()); if (handler == null) { error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele); return null; } /** 调用自定义的NamespaceHandler进行解析*/ return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd)); } /** * Decorate the given bean definition through a namespace handler, if applicable. * @param ele the current element * @param originalDef the current bean definition * @return the decorated bean definition */ public BeanDefinitionHolder decorateBeanDefinitionIfRequired(Element ele, BeanDefinitionHolder originalDef) { /** * 第三个参数是父类的bean,当对某个嵌套配置进行分析时,这里需要传父类的beanDefinition,这里传入的参数 * 其实是为了使用父类的scope属性,以备若子类没有配置scope时使用父类的属性,这里是顶层配置所以传null */ System.out.println("第三个参数是父类的bean,当对某个嵌套配置进行分析时,这里需要传父类的beanDefinition,这里传入的参数\n" + "其实是为了使用父类的scope属性,以备若子类没有配置scope时使用父类的属性,这里是顶层配置所以传null"); return decorateBeanDefinitionIfRequired(ele, originalDef, null); } /** * Decorate the given bean definition through a namespace handler, if applicable. * @param ele the current element * @param originalDef the current bean definition * @param containingBd the containing bean definition (if any) * @return the decorated bean definition * * 对于程序默认的标签的处理其实是直接略过的,因为默认的标签这里已经被处理完了,这里只对自定义 * 的标签或者说对bean的自定义属性感兴趣.在方法中实现了寻找自定义标签并根据自定义标签寻找命名 * 空间处理器. */ public BeanDefinitionHolder decorateBeanDefinitionIfRequired( Element ele, BeanDefinitionHolder originalDef, @Nullable BeanDefinition containingBd) { BeanDefinitionHolder finalDefinition = originalDef; // Decorate based on custom attributes first. NamedNodeMap attributes = ele.getAttributes(); /** 遍历所有的属性,看看是否有适用于修饰的属性*/ System.err.println("遍历所有的属性,看看是否有适用于修饰的属性"); for (int i = 0; i < attributes.getLength(); i++) { Node node = attributes.item(i); System.out.println(node.toString()); finalDefinition = decorateIfRequired(node, finalDefinition, containingBd); } // Decorate based on custom nested elements. NodeList children = ele.getChildNodes(); /** 遍历所有的子节点,看看是否有适用于修饰的子元素*/ for (int i = 0; i < children.getLength(); i++) { Node node = children.item(i); if (node.getNodeType() == Node.ELEMENT_NODE) { finalDefinition = decorateIfRequired(node, finalDefinition, containingBd); } } return finalDefinition; } /** * Decorate the given bean definition through a namespace handler, * if applicable. * @param node the current child node * @param originalDef the current bean definition * @param containingBd the containing bean definition (if any) * @return the decorated bean definition * * 首先获取属性或者元素命名空间,以此来判断元素或者属性是否适用于自定义标签的解析条件,找出 * 自定义类型所对应的NamespaceHandler并进行进一步解析, */ public BeanDefinitionHolder decorateIfRequired( Node node, BeanDefinitionHolder originalDef, @Nullable BeanDefinition containingBd) { /** 获取自定义名称的命名空间*/ String namespaceUri = getNamespaceURI(node); System.err.println("获取自定义名称的命名空间:" + namespaceUri); /** 对于非默认标签进行修饰*/ System.err.println("对于非默认标签进行修饰"); if (namespaceUri != null && !isDefaultNamespace(namespaceUri)) { /** 根据默认命名空间找到对应的处理器*/ System.err.println("根据默认命名空间找到对应的处理器"); NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri); System.err.println("NamespaceHandler: " +handler.toString()); if (handler != null) { /** 进行修饰*/ System.err.println("进行修饰"); BeanDefinitionHolder decorated = handler.decorate(node, originalDef, new ParserContext(this.readerContext, this, containingBd)); System.err.println("BeanDefinitionHolder: " + decorated.toString()); if (decorated != null) { return decorated; } } else if (namespaceUri.startsWith("http://www.springframework.org/schema/")) { error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", node); } else { // A custom namespace, not to be handled by Spring - maybe "xml:...". if (logger.isDebugEnabled()) { logger.debug("No Spring NamespaceHandler found for XML schema namespace [" + namespaceUri + "]"); } } } return originalDef; } @Nullable private BeanDefinitionHolder parseNestedCustomElement(Element ele, @Nullable BeanDefinition containingBd) { BeanDefinition innerDefinition = parseCustomElement(ele, containingBd); if (innerDefinition == null) { error("Incorrect usage of element '" + ele.getNodeName() + "' in a nested manner. " + "This tag cannot be used nested inside .", ele); return null; } String id = ele.getNodeName() + BeanDefinitionReaderUtils.GENERATED_BEAN_NAME_SEPARATOR + ObjectUtils.getIdentityHexString(innerDefinition); if (logger.isTraceEnabled()) { logger.trace("Using generated bean name [" + id + "] for nested custom element '" + ele.getNodeName() + "'"); } return new BeanDefinitionHolder(innerDefinition, id); } /** * Get the namespace URI for the supplied node. *

The default implementation uses {@link Node#getNamespaceURI}. * Subclasses may override the default implementation to provide a * different namespace identification mechanism. * @param node the node */ @Nullable public String getNamespaceURI(Node node) { return node.getNamespaceURI(); } /** * Get the local name for the supplied {@link Node}. *

The default implementation calls {@link Node#getLocalName}. * Subclasses may override the default implementation to provide a * different mechanism for getting the local name. * @param node the {@code Node} */ public String getLocalName(Node node) { return node.getLocalName(); } /** * Determine whether the name of the supplied node is equal to the supplied name. *

The default implementation checks the supplied desired name against both * {@link Node#getNodeName()} and {@link Node#getLocalName()}. *

Subclasses may override the default implementation to provide a different * mechanism for comparing node names. * @param node the node to compare * @param desiredName the name to check for */ public boolean nodeNameEquals(Node node, String desiredName) { return desiredName.equals(node.getNodeName()) || desiredName.equals(getLocalName(node)); } /** * Determine whether the given URI indicates the default namespace. */ public boolean isDefaultNamespace(@Nullable String namespaceUri) { return !StringUtils.hasLength(namespaceUri) || BEANS_NAMESPACE_URI.equals(namespaceUri); } /** * Determine whether the given node indicates the default namespace. * 确定给定节点是否指示默认命名空间。 */ public boolean isDefaultNamespace(Node node) { return isDefaultNamespace(getNamespaceURI(node)); } private boolean isDefaultValue(String value) { return !StringUtils.hasLength(value) || DEFAULT_VALUE.equals(value); } private boolean isCandidateElement(Node node) { return (node instanceof Element && (isDefaultNamespace(node) || !isDefaultNamespace(node.getParentNode()))); } }