BeanDefinitionParserDelegate.java 75.4 KB
Newer Older
C
congshuo_cnki 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
/*
 * 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";

99 100 101 102
	/**
	 * default-autowire 属性值之一:
	 * 实际上是会优先执行constructor然后是byType
	 */
C
congshuo_cnki 已提交
103 104
	public static final String DEFAULT_VALUE = "default";

105 106 107
	/**
	 * description元素必须在beans中的第一行,用于描述配置的信息
	 */
C
congshuo_cnki 已提交
108
	public static final String DESCRIPTION_ELEMENT = "description";
109 110 111 112
	/**
	 * default-autowire 属性值之一 默认属性值:
	 * no:不启用自动注入
	 */
C
congshuo_cnki 已提交
113 114
	public static final String AUTOWIRE_NO_VALUE = "no";

115 116 117 118
	/**
	 * default-autowire 属性值之一:
	 * 根据name注入
	 */
C
congshuo_cnki 已提交
119 120
	public static final String AUTOWIRE_BY_NAME_VALUE = "byName";

121 122 123 124 125
	/**
	 * default-autowire 属性值之一:
	 * 这个是会根据类型去注入,当找到了会直接注入,没有找到不会报错,
	 * 但是找到多个会报No unique bean of type的错误
	 */
C
congshuo_cnki 已提交
126 127
	public static final String AUTOWIRE_BY_TYPE_VALUE = "byType";

128 129 130 131
	/**
	 * default-autowire 属性值之一:
	 * 这个是通过构造注入
	 */
C
congshuo_cnki 已提交
132 133 134 135
	public static final String AUTOWIRE_CONSTRUCTOR_VALUE = "constructor";

	public static final String AUTOWIRE_AUTODETECT_VALUE = "autodetect";

136 137 138 139 140 141 142 143
	/**
	 * bean元素属性之一:
	 * name标签是bean的名称标识,Ioc容器中bean的name标签不能重复,同一个bean中
	 * 可以与id重复(name值可以等于id值)
	 *
	 * property 设值注入性之一:
	 * name 为类中要注入依赖项的名字。需要有set方法。name值与setXXX 中XXX一致,与声明的名字无关
	 */
C
congshuo_cnki 已提交
144 145 146 147
	public static final String NAME_ATTRIBUTE = "name";

	public static final String BEAN_ELEMENT = "bean";

148 149 150 151 152 153 154
	/**
	 *  property 设值注入性之一:
	 *  meta: 一个额外的属性,可以使用  BeanDefinition的getAttribute(key);方法获取,
	 *
	 * <meta key = "key" value = "values">
	 *
	 */
C
congshuo_cnki 已提交
155 156
	public static final String META_ELEMENT = "meta";

157 158 159 160 161 162 163
	/**
	 * bean元素属性之一:
	 * id标签是bean的唯一标识,Ioc容器中bean的id标签不能重复,否者报错
	 *
	 * id标签的值 在 同一个配置文件中是惟一的,
	 * 在多个spring文件中存在相同的id 或 name后面引入的配置会覆盖前面的bean
	 */
C
congshuo_cnki 已提交
164 165
	public static final String ID_ATTRIBUTE = "id";

166 167 168 169
	/**
	 * bean属性之一:
	 * spring中parent标签是指:某个<bean>的父类。这个类可以覆盖parent的属性
	 */
C
congshuo_cnki 已提交
170 171
	public static final String PARENT_ATTRIBUTE = "parent";

172 173 174
	/**
	 * class属性是bean常用属性,为bean的全限定类名,指向classpath下类定义所在位置
	 */
C
congshuo_cnki 已提交
175 176
	public static final String CLASS_ATTRIBUTE = "class";

177 178 179 180
	/**
	 * 使用abstract属性定义公共属性。bean使用abstract=true时,可以有class,
	 * 也可以没有class,一般与parent配合使用
	 */
C
congshuo_cnki 已提交
181 182
	public static final String ABSTRACT_ATTRIBUTE = "abstract";

183 184 185 186 187 188 189 190 191
	/**
	 * bean元素属性之一:
	 * 可以设置单例和多例:
	 * singleton: 详见下方注释
	 * prototype:当前模式bean处于多例模式
	 *   原型,每次请求(每次使用)创建新的实例,destroy方式失效(因为没有用到的实例会被垃圾回收)
	 * 	 不需要调用destory
	 * 	 懒加载失效
	 */
C
congshuo_cnki 已提交
192 193
	public static final String SCOPE_ATTRIBUTE = "scope";

194 195 196 197 198 199
	/**
	 * 当前bean处在单例模式下(默认)
	 * 指一个Bean容器中只存在一份
	 * 以单例模式创建的bean对象,在beans容器(IOC容器可以加载多个beans容器的配置文件)
	 * 中的对象都是同一个内存地址对象
	 */
C
congshuo_cnki 已提交
200 201
	private static final String SINGLETON_ATTRIBUTE = "singleton";

202 203
	/** 只有 true、false 用来指定bean是否在容器启动时初始化,为false时容器启动时初始化
	 * 用途: 通常用于解决spring循环引用的问题: */
C
congshuo_cnki 已提交
204 205
	public static final String LAZY_INIT_ATTRIBUTE = "lazy-init";

206 207 208
	/**
	 * autowire表示bean的自动装配
	 */
C
congshuo_cnki 已提交
209 210
	public static final String AUTOWIRE_ATTRIBUTE = "autowire";

211 212 213
	/**
	 * 值有 true, false、default  。autowire-candidate="false" 表示该对象不参与自动注入
	 */
C
congshuo_cnki 已提交
214 215
	public static final String AUTOWIRE_CANDIDATE_ATTRIBUTE = "autowire-candidate";

216 217 218 219 220 221 222
	/**
	 * primary的值有true和false两个可以选择。默认为false。当一个bean的primary设置为true,然后容器
	 * 中有多个与该bean相同类型的其他bean,此时,当使用@Autowired想要注入一个这个类型的bean时,
	 * 就不会因为容器中存在多个该类型的bean而出现异常。而是优先使用primary为true的bean。不过,
	 * 如果容器中不仅有多个该类型的bean,而且这些bean中有多个的primary的值设置为true,
	 * 那么使用byType注入还是会出错
	 */
C
congshuo_cnki 已提交
223 224
	public static final String PRIMARY_ATTRIBUTE = "primary";

225 226 227 228
	/**
	 * depends-on适用于表面上看起来两个bean之间没有使用属性之类的强连接的bean,但是两个bean又确实
	 * 存在前后依赖关系的情况,被depends-on链接的bean 先创建,后销毁,依赖他人的bean是先于被依赖bean销毁的
	 */
C
congshuo_cnki 已提交
229 230
	public static final String DEPENDS_ON_ATTRIBUTE = "depends-on";

231 232 233 234
	/**
	 * bean元素属性之一:
	 * init-method属性是bean的初始方法,在创建好bean后调用该方法
	 */
C
congshuo_cnki 已提交
235 236 237 238
	public static final String INIT_METHOD_ATTRIBUTE = "init-method";

	public static final String DESTROY_METHOD_ATTRIBUTE = "destroy-method";

239 240 241 242
	/**
	 * bean元素属性之一:
	 * factory-method工厂方法属性,通过该属性,我们可以调用一个指定的静态工厂方法,创建bean实例
	 */
C
congshuo_cnki 已提交
243 244
	public static final String FACTORY_METHOD_ATTRIBUTE = "factory-method";

245 246 247 248
	/**
	 * bean元素属性之一:
	 * factory-bean就是生成bean的工厂对象,factory-bean和factory-method属性一起使用
	 */
C
congshuo_cnki 已提交
249 250
	public static final String FACTORY_BEAN_ATTRIBUTE = "factory-bean";

251 252 253
	/**
	 * 通过构造函数注入
	 */
C
congshuo_cnki 已提交
254 255 256 257 258 259 260 261 262 263
	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";

264 265 266 267 268

	/**
	 * property 设值注入
	 * 通过setter对应的方法注入 。spring配置中property作为bean的属性。也就是指一个类中的成员。同时这个成员必须有set方法。
	 */
C
congshuo_cnki 已提交
269 270 271 272 273 274
	public static final String PROPERTY_ELEMENT = "property";

	public static final String REF_ATTRIBUTE = "ref";

	public static final String VALUE_ATTRIBUTE = "value";

275 276 277
	/**
	 * 方法的覆盖。注入bean的作用域小于当前bean时,希望每次可以拿到最新的注入bean。
	 */
C
congshuo_cnki 已提交
278 279
	public static final String LOOKUP_METHOD_ELEMENT = "lookup-method";

280 281 282
	/**
	 * 方法的替换 ,要实现spring的MethodReplacer接口
	 */
C
congshuo_cnki 已提交
283 284 285 286 287 288 289 290
	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";

291 292 293 294 295 296 297 298 299 300 301
	/**
	 * property 设值注入 之一:
	 * ref 为引用项bean的id 或name 。value 值为值类型
	 * 	<property name="....." ref="......" />就是找当前配置文件里的bean ,
	 * 	<ref bean ="....."/> 是寻找全局(可以到其他xml中)中的 bean;
	 * <ref>标签里有3种属性
	 * 	<ref bean="寻找全局(可以到其他xml中)中的 bean"/>,
	 * 	<ref local="关联当前xml的bean "/>,
	 * 	<ref parent="用于指定其依赖的父 JavaBean 定义"/>。
	 * 	在4.0BeanXSD中 ref 元素上的local 属性不再受支持
	 */
C
congshuo_cnki 已提交
302 303
	public static final String REF_ELEMENT = "ref";

304 305 306 307 308 309 310 311 312 313 314
	/**
	 * idref: idref元素只是一种防止错误的方法,可以将容器中另一个bean的id(一个字符串值,而不是引用)传递给一个
	 * <constructor-arg/>或<property/>元素(在某种意义上等同于<value/>)
	 *
	 * 	<bean id="theTargetBean" class="..."/>
	 * 		<bean id="theClientBean" class="...">
	 * 		<property name="targetName">
	 * 		<idref bean="theTargetBean"/>
	 * 		</property>
	 * 	</bean>
	 */
C
congshuo_cnki 已提交
315 316
	public static final String IDREF_ELEMENT = "idref";

317 318 319 320
	/**
	 * property 设值注入 之一:
	 * bean: 内部 Bean:当 Spring IoC 容器中的 bean1 只会被 bean2 引用,而不会被容器中任何其他 Bean 引用的时候,则可以将这个 bean1 以内部 Bean 的方式注入到 bean2 中。
	 */
C
congshuo_cnki 已提交
321 322 323 324
	public static final String BEAN_REF_ATTRIBUTE = "bean";

	public static final String PARENT_REF_ATTRIBUTE = "parent";

325 326 327 328
	/**
	 * property 设值注入 之一:
	 * value: 为属性注入字面值
	 */
C
congshuo_cnki 已提交
329 330 331 332
	public static final String VALUE_ELEMENT = "value";

	public static final String NULL_ELEMENT = "null";

333 334 335 336 337 338 339 340 341 342 343
	/**
	 * property 设值注入 之一:
	 * array:当属性为 java.util.Array 的时候  可以在集合上加 merge="true",允许与父类集合合并(继承的概念)
	 *   <property name="favs">
	 *       <array>
	 *           <value>足球</value>
	 *           <value>篮球</value>
	 *           <value>排球</value>
	 *       </array>
	 *   </property>
	 */
C
congshuo_cnki 已提交
344 345
	public static final String ARRAY_ELEMENT = "array";

346 347 348 349 350 351 352 353 354 355 356 357 358 359
	/**
	 * property 设值注入 之一:
	 * list: 当属性为 java.util.List 的时候,可以在集合上加 merge="true",允许与父类集合合并
	 *
	 * <bean id="boss" class="***">
	 *   <property name="favorites">
	 *     <list>
	 *       <value>唱歌</value>
	 *       <value>运动</value>
	 *       <value>读书</value>
	 *     </list>
	 *   </property>
	 * </bean>
	 */
C
congshuo_cnki 已提交
360 361
	public static final String LIST_ELEMENT = "list";

362 363 364 365 366 367 368 369 370 371 372 373 374
	/**
	 * property 设值注入 之一:
	 * set: 当属性为 java.util.Set 的时候  可以在集合上加 merge="true",允许与父类集合合并
	 * <bean id="boss" class="***">
	 *   <property name="favorites">
	 *     <set>
	 *       <value>唱歌</value>
	 *       <value>运动</value>
	 *       <value>读书</value>
	 *     </set>
	 *   </property>
	 *  </bean>
	 */
C
congshuo_cnki 已提交
375 376
	public static final String SET_ELEMENT = "set";

377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399
	/**
	 * property 设值注入 之一:
	 * map: 当属性为 java.util.Map 的时候 可以在集合上加 merge="true",允许与父类集合合并
	 *
	 * <bean id="boss" class="***">
	 *   <property name="favorites">
	 *     <map>
	 *       <entry>
	 *         <key><value>key01</value></key>
	 *         <value>唱歌</value>
	 *       </entry>
	 *       <entry>
	 *         <key><value>key02</value></key>
	 *         <value>运动</value>
	 *       </entry>
	 *       <entry>
	 *         <key><ref bean="keyBean" /></key>
	 *         <ref bean="valueBean" />
	 *       </entry>
	 *     </map>
	 *   </property>
	 * </bean>
	 */
C
congshuo_cnki 已提交
400 401 402 403 404 405 406 407 408 409 410 411
	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";

412 413 414 415 416 417 418 419 420 421 422 423 424 425 426
	/**
	 * property 设值注入 之一:
	 * props: 当属性为 java.util.Properties 的时候 可以在集合上加 merge="true",允许与父类集合合并
	 *
	 * <bean id="boss" class="***">
	 *   <property name="favorites">
	 *       <props>
	 *         <prop key="p01">唱歌</prop>
	 *         <prop key="p02">运动</prop>
	 *         <prop key="p03">读书</prop>
	 *       </props>
	 *     </properties>
	 *   </property>
	 * </bean>
	 */
C
congshuo_cnki 已提交
427 428 429 430 431 432
	public static final String PROPS_ELEMENT = "props";

	public static final String PROP_ELEMENT = "prop";

	public static final String MERGE_ATTRIBUTE = "merge";

433 434 435
	/**
	 * 当bean的注入项有多个实现时,使用Qualifier指定要注入的bean的标识
	 */
C
congshuo_cnki 已提交
436 437 438 439
	public static final String QUALIFIER_ELEMENT = "qualifier";

	public static final String QUALIFIER_ATTRIBUTE_ELEMENT = "attribute";

440 441 442 443
	/** 全局懒加载 作用于beans 身上
	 *  spring 配置默认default-lazy-init为false,当属性default-lazy-init设置成true时,
	 *  spring不会再去加载整个对象的实例图,大大减少了初始化的时间,减少spring的启动时间
	 */
C
congshuo_cnki 已提交
444 445
	public static final String DEFAULT_LAZY_INIT_ATTRIBUTE = "default-lazy-init";

446 447 448 449
	/**
	 * 从spring2.0M2开始,beans支持default-merge=”true“
	 * 子类不需要重新定义父类的List型属性中已定义过的内容
	 */
C
congshuo_cnki 已提交
450 451
	public static final String DEFAULT_MERGE_ATTRIBUTE = "default-merge";

452 453 454 455
	/**
	 * bean 注入属性方式总体来看有五个值:
	 * no、default、byType、byName、constructor
	 */
C
congshuo_cnki 已提交
456 457
	public static final String DEFAULT_AUTOWIRE_ATTRIBUTE = "default-autowire";

458 459 460 461 462
	/**
	 * 候选者属性,自动装配时既匹配则被包含。不匹配的排除在外。
	 * 此属性的值允许使用模式字符串,例如我们制定default-autowire-candidates='abc',
	 * 则所有以‘abc’结尾的Bean都将被自己装配。他还支持多个字符串,可以通过空格等分割。
	 */
C
congshuo_cnki 已提交
463 464
	public static final String DEFAULT_AUTOWIRE_CANDIDATES_ATTRIBUTE = "default-autowire-candidates";

465 466 467 468 469 470
	/**
	 * default-init-method="init"
	 * 很多Bean都需要配置初始化方法和销毁方法,那么可以在beans标签中配置default-init-method和
	 * default-destroy-method来指定所有Bean的默认初始化方法和销毁方法(init和下方的destroy是
	 * bean中的方法)
	 */
C
congshuo_cnki 已提交
471 472
	public static final String DEFAULT_INIT_METHOD_ATTRIBUTE = "default-init-method";

473 474 475
	/**
	 * default-destroy-method="destroy"
	 */
C
congshuo_cnki 已提交
476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560
	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<String> 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);
C
congshuo_cnki 已提交
561
		System.out.println("最后将默认的DocumentDefaultsDefinition,存放(注册)到List<DefaultsDefinition> ");
C
congshuo_cnki 已提交
562 563 564 565 566 567 568 569 570 571
	}

	/**
	 * 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)
572 573 574 575 576 577
	 *
	 * 使用默认的惰性初始化、自动装配、依赖性检查设置、初始化方法、销毁方法和合并设置填充给定的 DocumentDefaultsDefinition 实例。
	 * 通过回退到 parentDefaults} 来支持嵌套的“bean”元素用例,以防默认值未在本地显式设置。
	 * @param defaults 默认默认填充
	 * @param parentDefaults 父 BeanDefinitionParserDelegate(如果有) 默认回退
	 * @param root 当前 bean 定义文档的根元素(或嵌套 beans 元素)
C
congshuo_cnki 已提交
578 579
	 */
	protected void populateDefaults(DocumentDefaultsDefinition defaults, @Nullable DocumentDefaultsDefinition parentDefaults, Element root) {
580
		// 是否进行懒加载
C
congshuo_cnki 已提交
581
		System.err.println("委托类解析 BeanDefinitionParserDelegate.populateDefaults解析xml");
C
congshuo_cnki 已提交
582
		String lazyInit = root.getAttribute(DEFAULT_LAZY_INIT_ATTRIBUTE);
C
congshuo_cnki 已提交
583 584
		System.out.println("注这里一共3个;一个为默认类型,一个当前类,一个父类");
		System.out.println("需设置默认类型 - 检查当前的懒加载为:" + lazyInit + " 如果当前类手动设置了其模式会向上委托,保持与父类一致");
C
congshuo_cnki 已提交
585 586 587 588 589
		if (isDefaultValue(lazyInit)) {
			// Potentially inherited from outer <beans> sections, otherwise falling back to false.
			lazyInit = (parentDefaults != null ? parentDefaults.getLazyInit() : FALSE_VALUE);
		}
		defaults.setLazyInit(lazyInit);
590
		System.err.println("当前的beans是否进行懒加载" + DEFAULT_LAZY_INIT_ATTRIBUTE + ":" + lazyInit);
C
congshuo_cnki 已提交
591 592 593 594 595 596
		String merge = root.getAttribute(DEFAULT_MERGE_ATTRIBUTE);
		if (isDefaultValue(merge)) {
			// Potentially inherited from outer <beans> sections, otherwise falling back to false.
			merge = (parentDefaults != null ? parentDefaults.getMerge() : FALSE_VALUE);
		}
		defaults.setMerge(merge);
597
		System.err.println("子类不需要重新定义父类的List型属性中已定义过的内容" + DEFAULT_MERGE_ATTRIBUTE + ":" + merge);
C
congshuo_cnki 已提交
598 599 600 601 602 603 604 605
		String autowire = root.getAttribute(DEFAULT_AUTOWIRE_ATTRIBUTE);
		if (isDefaultValue(autowire)) {
			// Potentially inherited from outer <beans> 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));
606
			System.err.println("所有以此属性结尾的都会被自动装配:" + DEFAULT_AUTOWIRE_CANDIDATES_ATTRIBUTE + ":" + autowire);
C
congshuo_cnki 已提交
607 608 609
		}
		else if (parentDefaults != null) {
			defaults.setAutowireCandidates(parentDefaults.getAutowireCandidates());
610
			System.err.println("所有以此属性结尾的都会被自动装配" + ":" + parentDefaults.getAutowireCandidates());
C
congshuo_cnki 已提交
611 612 613 614
		}

		if (root.hasAttribute(DEFAULT_INIT_METHOD_ATTRIBUTE)) {
			defaults.setInitMethod(root.getAttribute(DEFAULT_INIT_METHOD_ATTRIBUTE));
615
			System.err.println("初始化方法为:" + root.getAttribute(DEFAULT_INIT_METHOD_ATTRIBUTE));
C
congshuo_cnki 已提交
616 617 618
		}
		else if (parentDefaults != null) {
			defaults.setInitMethod(parentDefaults.getInitMethod());
619
			System.err.println("初始化方法为:" + parentDefaults.getInitMethod());
C
congshuo_cnki 已提交
620 621 622 623
		}

		if (root.hasAttribute(DEFAULT_DESTROY_METHOD_ATTRIBUTE)) {
			defaults.setDestroyMethod(root.getAttribute(DEFAULT_DESTROY_METHOD_ATTRIBUTE));
624
			System.err.println("销毁方法为:" + root.getAttribute(DEFAULT_DESTROY_METHOD_ATTRIBUTE));
C
congshuo_cnki 已提交
625 626 627
		}
		else if (parentDefaults != null) {
			defaults.setDestroyMethod(parentDefaults.getDestroyMethod());
628
			System.err.println("销毁方法为:" + parentDefaults.getDestroyMethod());
C
congshuo_cnki 已提交
629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678
		}

		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 <beans/>} 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 <beans/>} element.
	 */
	@Nullable
	public String[] getAutowireCandidatePatterns() {
		String candidatePattern = this.defaults.getAutowireCandidates();
		return (candidatePattern != null ? StringUtils.commaDelimitedListToStringArray(candidatePattern) : null);
	}


	/**
	 * Parses the supplied {@code <bean>} 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 <bean>} element. May return {@code null}
	 * if there were errors during parse. Errors are reported to the
	 * {@link org.springframework.beans.factory.parsing.ProblemReporter}.
679 680 681 682 683
	 *
	 * 1.提取元素中的id以及name属性。
	 * 2.进一步解析其他所有属性并统一封装至GenericBeanDefinition类型的实例中。
	 * 3.如果检测bean没有指定beanName,那么使用默认规则为此Bean生成BeanName(beanId).
	 * 4.将获得到的信息封装到BeanDefinitionHolder的实例中。
C
congshuo_cnki 已提交
684 685 686
	 */
	@Nullable
	public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) {
C
congshuo_cnki 已提交
687 688 689 690
		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的实例中。");
691
		System.err.println("解析:BeanDefinition");
692
		// 解析id属性
C
congshuo_cnki 已提交
693
		String id = ele.getAttribute(ID_ATTRIBUTE);
694
		System.err.println("获取当前bean的id:" + id);
695
		// 解析name属性
C
congshuo_cnki 已提交
696
		String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
697
		System.err.println("获取name属性数组的方式:" + nameAttr);
698
        // 分割name属性 得到别名的集合
C
congshuo_cnki 已提交
699 700 701 702
		List<String> aliases = new ArrayList<>();
		if (StringUtils.hasLength(nameAttr)) {
			String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
			aliases.addAll(Arrays.asList(nameArr));
703
			System.err.println("设置aliases");
C
congshuo_cnki 已提交
704 705 706 707 708 709 710 711 712 713
		}

		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");
			}
		}
714
		System.err.println("获取当前bean的name:" + beanName);
C
congshuo_cnki 已提交
715 716 717
		if (containingBean == null) {
			checkNameUniqueness(beanName, aliases, ele);
		}
C
congshuo_cnki 已提交
718
		System.out.println("AbstractBeanDefinition --- parseBeanDefinitionElement解析");
C
congshuo_cnki 已提交
719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789
		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<String> 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 <beans> 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();
790
			System.err.println("获取当前的className:" + className);
C
congshuo_cnki 已提交
791 792 793 794
		}
		String parent = null;
		if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
			parent = ele.getAttribute(PARENT_ATTRIBUTE);
795
			System.err.println("获取当前bean的:parent:" + parent);
C
congshuo_cnki 已提交
796 797 798
		}

		try {
799
			/** 创建用于承载属性的AbstractBeanDefinition类型的GenericBeanDefinition*/
C
congshuo_cnki 已提交
800
			System.out.println("创建用于承载属性的AbstractBeanDefinition类型的GenericBeanDefinition");
C
congshuo_cnki 已提交
801 802
			AbstractBeanDefinition bd = createBeanDefinition(className, parent);

803
			/** 硬编码解析bean的给种属性*/
C
congshuo_cnki 已提交
804
			System.out.println("parseBeanDefinitionAttributes 硬编码解析bean的给种属性");
C
congshuo_cnki 已提交
805
			parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
C
congshuo_cnki 已提交
806
			System.out.println("AbstractBeanDefinition:" + bd.toString());
807
			/** 提取description*/
C
congshuo_cnki 已提交
808
			System.out.println("提取description");
C
congshuo_cnki 已提交
809 810
			bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));

811
			/** 解析元数据*/
C
congshuo_cnki 已提交
812
			System.out.println("解析元数据");
C
congshuo_cnki 已提交
813
			parseMetaElements(ele, bd);
814
			/** 解析lookup-method 属性*/
C
congshuo_cnki 已提交
815
			System.out.println("解析lookup-method 属性");
C
congshuo_cnki 已提交
816
			parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
817
			/** 解析replaced-method 属性*/
C
congshuo_cnki 已提交
818
			System.out.println("解析replaced-method 属性");
C
congshuo_cnki 已提交
819 820
			parseReplacedMethodSubElements(ele, bd.getMethodOverrides());

821
			/** 解析构造函数参数*/
C
congshuo_cnki 已提交
822
			System.out.println("解析构造函数参数");
C
congshuo_cnki 已提交
823
			parseConstructorArgElements(ele, bd);
824
			/** 解析property子元素*/
C
congshuo_cnki 已提交
825
			System.out.println("解析property子元素");
C
congshuo_cnki 已提交
826
			parsePropertyElements(ele, bd);
827
			/** 解析qualifier子元素*/
C
congshuo_cnki 已提交
828
			System.out.println("解析qualifier子元素");
C
congshuo_cnki 已提交
829 830 831 832
			parseQualifierElements(ele, bd);

			bd.setResource(this.readerContext.getResource());
			bd.setSource(extractSource(ele));
C
congshuo_cnki 已提交
833
			System.out.println("AbstractBeanDefinition:" + bd.toString());
C
congshuo_cnki 已提交
834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860
			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) {
861
        //如果设置singleton直接报错 因为升级成了scope属性
C
congshuo_cnki 已提交
862
		System.err.println("如果设置singleton直接报错 因为升级成了scope属性");
C
congshuo_cnki 已提交
863 864 865
		if (ele.hasAttribute(SINGLETON_ATTRIBUTE)) {
			error("Old 1.x 'singleton' attribute in use - upgrade to 'scope' declaration", ele);
		}
866
		//解忻scope属性
C
congshuo_cnki 已提交
867 868
		else if (ele.hasAttribute(SCOPE_ATTRIBUTE)) {
			bd.setScope(ele.getAttribute(SCOPE_ATTRIBUTE));
869
			System.err.println("parseBeanDefinitionAttributes 解析scope属性:" + ele.getAttribute(SCOPE_ATTRIBUTE));
C
congshuo_cnki 已提交
870 871 872 873
		}
		else if (containingBean != null) {
			// Take default from containing bean in case of an inner bean definition.
			bd.setScope(containingBean.getScope());
874
			System.err.println("parseBeanDefinitionAttributes 解析scope属性 在嵌入beanDifinition情况下且没有单独指定 scope 属性则佼用父类默认的属性:" + containingBean.getScope());
C
congshuo_cnki 已提交
875 876 877 878 879 880 881
		}

		if (ele.hasAttribute(ABSTRACT_ATTRIBUTE)) {
			bd.setAbstract(TRUE_VALUE.equals(ele.getAttribute(ABSTRACT_ATTRIBUTE)));
		}

		String lazyInit = ele.getAttribute(LAZY_INIT_ATTRIBUTE);
882

C
congshuo_cnki 已提交
883 884 885 886
		if (isDefaultValue(lazyInit)) {
			lazyInit = this.defaults.getLazyInit();
		}
		bd.setLazyInit(TRUE_VALUE.equals(lazyInit));
887
		System.err.println("解析lazy-init属性:" + bd.getLazyInit());
C
congshuo_cnki 已提交
888 889 890

		String autowire = ele.getAttribute(AUTOWIRE_ATTRIBUTE);
		bd.setAutowireMode(getAutowireMode(autowire));
891
		System.err.println("解析autowire属性:" + getAutowireMode(autowire));
C
congshuo_cnki 已提交
892 893 894
		if (ele.hasAttribute(DEPENDS_ON_ATTRIBUTE)) {
			String dependsOn = ele.getAttribute(DEPENDS_ON_ATTRIBUTE);
			bd.setDependsOn(StringUtils.tokenizeToStringArray(dependsOn, MULTI_VALUE_ATTRIBUTE_DELIMITERS));
895
			System.err.println("解析dependsOn属性:" + bd.getDescription());
C
congshuo_cnki 已提交
896 897 898 899 900 901 902 903 904 905 906 907 908
		}

		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));
		}
909
		System.err.println("解析autowireCandidate属性:" + TRUE_VALUE.equals(autowireCandidate));
C
congshuo_cnki 已提交
910 911 912

		if (ele.hasAttribute(PRIMARY_ATTRIBUTE)) {
			bd.setPrimary(TRUE_VALUE.equals(ele.getAttribute(PRIMARY_ATTRIBUTE)));
913
			System.err.println("解析primary属性:" + TRUE_VALUE.equals(ele.getAttribute(PRIMARY_ATTRIBUTE)));
C
congshuo_cnki 已提交
914 915 916 917 918
		}

		if (ele.hasAttribute(INIT_METHOD_ATTRIBUTE)) {
			String initMethodName = ele.getAttribute(INIT_METHOD_ATTRIBUTE);
			bd.setInitMethodName(initMethodName);
919
			System.err.println("解析initMethodName属性:" + initMethodName);
C
congshuo_cnki 已提交
920 921 922 923
		}
		else if (this.defaults.getInitMethod() != null) {
			bd.setInitMethodName(this.defaults.getInitMethod());
			bd.setEnforceInitMethod(false);
924
			System.err.println("解析initMethodName属性:" + this.defaults.getInitMethod());
C
congshuo_cnki 已提交
925 926 927 928 929
		}

		if (ele.hasAttribute(DESTROY_METHOD_ATTRIBUTE)) {
			String destroyMethodName = ele.getAttribute(DESTROY_METHOD_ATTRIBUTE);
			bd.setDestroyMethodName(destroyMethodName);
930
			System.err.println("解析destroyMethodName属性:" + destroyMethodName);
C
congshuo_cnki 已提交
931 932 933 934
		}
		else if (this.defaults.getDestroyMethod() != null) {
			bd.setDestroyMethodName(this.defaults.getDestroyMethod());
			bd.setEnforceDestroyMethod(false);
935
			System.err.println("解析destroyMethodName属性:" + this.defaults.getDestroyMethod());
C
congshuo_cnki 已提交
936 937 938 939
		}

		if (ele.hasAttribute(FACTORY_METHOD_ATTRIBUTE)) {
			bd.setFactoryMethodName(ele.getAttribute(FACTORY_METHOD_ATTRIBUTE));
940
			System.err.println("解析factoryMethodName属性:" + bd.getFactoryMethodName());
C
congshuo_cnki 已提交
941 942 943
		}
		if (ele.hasAttribute(FACTORY_BEAN_ATTRIBUTE)) {
			bd.setFactoryBeanName(ele.getAttribute(FACTORY_BEAN_ATTRIBUTE));
944
			System.err.println("解析factoryBeanName属性:" + bd.getFactoryBeanName());
C
congshuo_cnki 已提交
945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967
		}

		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) {
968
		/** 获取当前节点的所有子元素*/
C
congshuo_cnki 已提交
969 970
		NodeList nl = ele.getChildNodes();
		for (int i = 0; i < nl.getLength(); i++) {
971
			/** 获取当前的节点*/
C
congshuo_cnki 已提交
972
			Node node = nl.item(i);
973
			/** 提取meta*/
C
congshuo_cnki 已提交
974
			System.out.println("获取当前的节点:" + node.toString());
C
congshuo_cnki 已提交
975 976 977 978
			if (isCandidateElement(node) && nodeNameEquals(node, META_ELEMENT)) {
				Element metaElement = (Element) node;
				String key = metaElement.getAttribute(KEY_ATTRIBUTE);
				String value = metaElement.getAttribute(VALUE_ATTRIBUTE);
979 980 981
				System.err.println("获取当前meta标签的key:" + key);
				System.err.println("获取当前meta标签的value:" + value);
				/** 使用key、value构造 BeanMetadataAttribute*/
C
congshuo_cnki 已提交
982 983
				BeanMetadataAttribute attribute = new BeanMetadataAttribute(key, value);
				attribute.setSource(extractSource(metaElement));
984
				/** 记录信息*/
C
congshuo_cnki 已提交
985
				attributeAccessor.addMetadataAttribute(attribute);
C
congshuo_cnki 已提交
986 987
				System.out.println("记录信息");
				System.out.println("使用key、value构造 BeanMetadataAttribute:" + attribute.toString());
C
congshuo_cnki 已提交
988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064
			}
		}
	}

	/**
	 * 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);
1065
			/** 仅当在spring默认bean的子元素下切为 lookup-method时 有效*/
C
congshuo_cnki 已提交
1066 1067
			if (isCandidateElement(node) && nodeNameEquals(node, LOOKUP_METHOD_ELEMENT)) {
				Element ele = (Element) node;
1068
				/** 获取要修饰的方法*/
C
congshuo_cnki 已提交
1069
				String methodName = ele.getAttribute(NAME_ATTRIBUTE);
1070 1071
				System.err.println("lookup-method下的方法名称" + methodName);
				/** 获取配置返回的bean*/
C
congshuo_cnki 已提交
1072
				String beanRef = ele.getAttribute(BEAN_ELEMENT);
1073 1074
				System.err.println("lookup-method下的bean指向" + beanRef);
				System.err.println("使用LookupOverride类型的实体类来进行数据承载并记录在AbstractBeanDefinition中的methodOverrides属性中");
C
congshuo_cnki 已提交
1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088
				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);
1089
			/** 仅当在spring默认bean的子元素下切为 replaced-method时 有效*/
C
congshuo_cnki 已提交
1090 1091
			if (isCandidateElement(node) && nodeNameEquals(node, REPLACED_METHOD_ELEMENT)) {
				Element replacedMethodEle = (Element) node;
1092
				/** 提取要替换的据方法*/
C
congshuo_cnki 已提交
1093
				String name = replacedMethodEle.getAttribute(NAME_ATTRIBUTE);
1094 1095
				System.err.println("replaced-method 替换方法的名称为:" + name);
				/** 提取对应的新的替换方法*/
C
congshuo_cnki 已提交
1096
				String callback = replacedMethodEle.getAttribute(REPLACER_ATTRIBUTE);
1097
				System.err.println("replaced-method 替换新的方法的名称的引用" + callback);
C
congshuo_cnki 已提交
1098 1099 1100 1101 1102
				ReplaceOverride replaceOverride = new ReplaceOverride(name, callback);
				// Look for arg-type match elements.
				List<Element> argTypeEles = DomUtils.getChildElementsByTagName(replacedMethodEle, ARG_TYPE_ELEMENT);
				for (Element argTypeEle : argTypeEles) {
					String match = argTypeEle.getAttribute(ARG_TYPE_MATCH_ATTRIBUTE);
1103
					System.err.println("replaced-method 记录参数" + match);
C
congshuo_cnki 已提交
1104 1105 1106 1107 1108
					match = (StringUtils.hasText(match) ? match : DomUtils.getTextValue(argTypeEle));
					if (StringUtils.hasText(match)) {
						replaceOverride.addTypeIdentifier(match);
					}
				}
1109
				System.err.println("使用replaceOverride类型的实体类来进行数据承载并记录在AbstractBeanDefinition中的methodOverrides属性中");
C
congshuo_cnki 已提交
1110 1111 1112 1113 1114 1115 1116 1117
				replaceOverride.setSource(extractSource(replacedMethodEle));
				overrides.addOverride(replaceOverride);
			}
		}
	}

	/**
	 * Parse a constructor-arg element.
1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128
	 *
	 * 如果配置文件中指定了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属性中
C
congshuo_cnki 已提交
1129 1130 1131
	 */
	public void parseConstructorArgElement(Element ele, BeanDefinition bd) {
		String indexAttr = ele.getAttribute(INDEX_ATTRIBUTE);
1132
		System.err.println("constructor-arg 的index属性:" + indexAttr);
C
congshuo_cnki 已提交
1133
		String typeAttr = ele.getAttribute(TYPE_ATTRIBUTE);
1134
		System.err.println("constructor-arg 的type属性:" + typeAttr);
C
congshuo_cnki 已提交
1135
		String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
1136
		System.err.println("constructor-arg 的name属性:" + nameAttr);
C
congshuo_cnki 已提交
1137 1138 1139 1140 1141 1142 1143 1144 1145
		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));
1146
						//解析 ele 对应的罚性元素
C
congshuo_cnki 已提交
1147
						Object value = parsePropertyValue(ele, bd, null);
1148

C
congshuo_cnki 已提交
1149 1150 1151 1152 1153 1154 1155 1156
						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));
1157
						//不允许重复指定相同参数
C
congshuo_cnki 已提交
1158 1159 1160 1161
						if (bd.getConstructorArgumentValues().hasIndexedArgumentValue(index)) {
							error("Ambiguous constructor-arg entries for index " + index, ele);
						}
						else {
1162
							System.err.println("constructor-arg-ConstructorArgumentValues.IndexedArgumentValue:" + valueHolder.toString());
C
congshuo_cnki 已提交
1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176
							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 {
1177
				/** 没有index属性则忽略去属性,自动寻找*/
C
congshuo_cnki 已提交
1178 1179 1180 1181 1182 1183 1184 1185 1186 1187
				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));
1188
				System.err.println("constructor-arg-ConstructorArgumentValues.GenericArgumentValue:" + valueHolder.toString());
C
congshuo_cnki 已提交
1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200
				bd.getConstructorArgumentValues().addGenericArgumentValue(valueHolder);
			}
			finally {
				this.parseState.pop();
			}
		}
	}

	/**
	 * Parse a property element.
	 */
	public void parsePropertyElement(Element ele, BeanDefinition bd) {
1201
		/** 获取元素中的name值*/
C
congshuo_cnki 已提交
1202 1203 1204 1205 1206 1207 1208
		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 {
1209
			// 不允许多次对同一属性赋值
C
congshuo_cnki 已提交
1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269
			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.
1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284
	 *
	 * 1.略过description或者meta
	 * 2.提取constructor-arg上的ref和value属性,以便于根据规则验证正确性其规则在constructor-arg上不存在以下情况
	 *   同时既有ref属性又有value属性
	 *   存在ref属性或者value属性又有子元素
	 * 3.ref属性的处理。使用RuntimeBeanReference封装对应的ref名称,如:
	 *   <constructor-arg ref="a"></constructor-arg>
	 * 4.value属性的处理。使用TypedStringValue封装,如:
	 *   <constructor-arg value="a"></constructor-arg>
	 * 5.子元素的处理,如:
	 *   <constructor-arg>
	 *       <map>
	 *           <entry key="key" value="value"></entry>
	 *       </map>
	 *   </constructor-arg>
C
congshuo_cnki 已提交
1285 1286 1287 1288 1289 1290 1291
	 */
	@Nullable
	public Object parsePropertyValue(Element ele, BeanDefinition bd, @Nullable String propertyName) {
		String elementName = (propertyName != null ?
				"<property> element for property '" + propertyName + "'" :
				"<constructor-arg> element");

1292 1293 1294 1295
		/**
		 * Should only have one child element: ref, value, list, etc.
		 * 一个属性只能对应一种类型,ref、value、list等。
		 */
C
congshuo_cnki 已提交
1296 1297 1298 1299
		NodeList nl = ele.getChildNodes();
		Element subElement = null;
		for (int i = 0; i < nl.getLength(); i++) {
			Node node = nl.item(i);
1300
			/** 对应description 或者 meta不处理*/
C
congshuo_cnki 已提交
1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311
			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;
				}
			}
		}
1312 1313 1314
		/**
		 * 解析constructor-arg上的ref属性
		 */
C
congshuo_cnki 已提交
1315
		boolean hasRefAttribute = ele.hasAttribute(REF_ATTRIBUTE);
1316 1317 1318
		/**
		 * 解析constructor-arg上的value属性
		 */
C
congshuo_cnki 已提交
1319 1320 1321 1322 1323
		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);
1324 1325 1326 1327 1328
			/**
			 * 在constructor-arg上不存在
			 *   1.同时既有ref属性又有value属性
			 *   2.存在ref属性或者value属性又有子元素
			 */
C
congshuo_cnki 已提交
1329 1330 1331
		}

		if (hasRefAttribute) {
1332
			// ref属性处理,使用RuntimeBeanReference封装的ref名称
C
congshuo_cnki 已提交
1333
			String refName = ele.getAttribute(REF_ATTRIBUTE);
1334
			System.err.println("constructor-arg 的refName:" + refName);
C
congshuo_cnki 已提交
1335 1336 1337 1338
			if (!StringUtils.hasText(refName)) {
				error(elementName + " contains empty 'ref' attribute", ele);
			}
			RuntimeBeanReference ref = new RuntimeBeanReference(refName);
1339
			System.err.println("将当前的refName 封装成 RuntimeBeanReference:" + ref.toString());
C
congshuo_cnki 已提交
1340 1341 1342 1343
			ref.setSource(extractSource(ele));
			return ref;
		}
		else if (hasValueAttribute) {
1344
			/** value 属性处理,使用TypeStringValue封装*/
C
congshuo_cnki 已提交
1345 1346
			TypedStringValue valueHolder = new TypedStringValue(ele.getAttribute(VALUE_ATTRIBUTE));
			valueHolder.setSource(extractSource(ele));
1347
			System.err.println("将当前的value 封装成TypedStringValue:" + ele.getAttribute(VALUE_ATTRIBUTE));
C
congshuo_cnki 已提交
1348 1349 1350
			return valueHolder;
		}
		else if (subElement != null) {
1351
			/** 解析子元素*/
C
congshuo_cnki 已提交
1352 1353 1354
			return parsePropertySubElement(subElement, bd);
		}
		else {
1355
			/** 既没有ref 也没有 value spring蒙圈了 直接报错*/
C
congshuo_cnki 已提交
1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394
			// 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 <value>} 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.
1395
			/** 解析local*/
C
congshuo_cnki 已提交
1396 1397 1398 1399
			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.
1400
				/** 解析parent*/
C
congshuo_cnki 已提交
1401 1402 1403 1404 1405 1406 1407 1408 1409 1410 1411 1412 1413 1414 1415
				refName = ele.getAttribute(PARENT_REF_ATTRIBUTE);
				toParent = true;
				if (!StringUtils.hasLength(refName)) {
					error("'bean' or 'parent' is required for <ref> element", ele);
					return null;
				}
			}
			if (!StringUtils.hasText(refName)) {
				error("<ref> element contains empty target attribute", ele);
				return null;
			}
			RuntimeBeanReference ref = new RuntimeBeanReference(refName, toParent);
			ref.setSource(extractSource(ele));
			return ref;
		}
1416
		/** 对idref子元素解析*/
C
congshuo_cnki 已提交
1417 1418 1419
		else if (nodeNameEquals(ele, IDREF_ELEMENT)) {
			return parseIdRefElement(ele);
		}
1420
		/** 对value子元素解析*/
C
congshuo_cnki 已提交
1421 1422 1423
		else if (nodeNameEquals(ele, VALUE_ELEMENT)) {
			return parseValueElement(ele, defaultValueType);
		}
1424
		/** 对null子元素进行解析*/
C
congshuo_cnki 已提交
1425 1426 1427 1428 1429 1430 1431
		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;
		}
1432
		/** 解析array子元素*/
C
congshuo_cnki 已提交
1433 1434 1435
		else if (nodeNameEquals(ele, ARRAY_ELEMENT)) {
			return parseArrayElement(ele, bd);
		}
1436
		/** 解析list子元素*/
C
congshuo_cnki 已提交
1437 1438 1439
		else if (nodeNameEquals(ele, LIST_ELEMENT)) {
			return parseListElement(ele, bd);
		}
1440
		/** 解析set子元素*/
C
congshuo_cnki 已提交
1441 1442 1443
		else if (nodeNameEquals(ele, SET_ELEMENT)) {
			return parseSetElement(ele, bd);
		}
1444
		/** 解析map子元素*/
C
congshuo_cnki 已提交
1445 1446 1447
		else if (nodeNameEquals(ele, MAP_ELEMENT)) {
			return parseMapElement(ele, bd);
		}
1448
		/** 解析props子元素*/
C
congshuo_cnki 已提交
1449 1450 1451 1452 1453 1454 1455 1456 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516 1517 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681 1682 1683 1684 1685 1686 1687 1688 1689 1690 1691 1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724 1725 1726 1727 1728 1729 1730 1731 1732 1733 1734 1735 1736 1737 1738 1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759 1760 1761 1762 1763 1764 1765 1766 1767 1768 1769 1770 1771 1772 1773 1774 1775 1776 1777 1778 1779 1780 1781 1782 1783 1784 1785 1786
		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 <idref> element", ele);
			return null;
		}
		if (!StringUtils.hasText(refName)) {
			error("<idref> 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 <value> 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<Object> parseListElement(Element collectionEle, @Nullable BeanDefinition bd) {
		String defaultElementType = collectionEle.getAttribute(VALUE_TYPE_ATTRIBUTE);
		NodeList nl = collectionEle.getChildNodes();
		ManagedList<Object> 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<Object> parseSetElement(Element collectionEle, @Nullable BeanDefinition bd) {
		String defaultElementType = collectionEle.getAttribute(VALUE_TYPE_ATTRIBUTE);
		NodeList nl = collectionEle.getChildNodes();
		ManagedSet<Object> 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<Object> 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<Object, Object> parseMapElement(Element mapEle, @Nullable BeanDefinition bd) {
		String defaultKeyType = mapEle.getAttribute(KEY_TYPE_ATTRIBUTE);
		String defaultValueType = mapEle.getAttribute(VALUE_TYPE_ATTRIBUTE);

		List<Element> entryEles = DomUtils.getChildElementsByTagName(mapEle, ENTRY_ELEMENT);
		ManagedMap<Object, Object> 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("<entry> element is only allowed to contain one <key> sub-element", entryEle);
						}
						else {
							keyEle = candidateEle;
						}
					}
					else {
						// Child element is what we're looking for.
						if (nodeNameEquals(candidateEle, DESCRIPTION_ELEMENT)) {
							// the element is a <description> -> ignore it
						}
						else if (valueEle != null) {
							error("<entry> 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("<entry> element is only allowed to contain either " +
						"a 'key' attribute OR a 'key-ref' attribute OR a <key> 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("<entry> 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("<entry> 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("<entry> element is only allowed to contain either " +
						"'value' attribute OR 'value-ref' attribute OR <value> sub-element", entryEle);
			}
			if ((hasValueTypeAttribute && hasValueRefAttribute) ||
				(hasValueTypeAttribute && !hasValueAttribute) ||
					(hasValueTypeAttribute && valueEle != null)) {
				error("<entry> 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("<entry> 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("<entry> 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("<key> 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<Element> 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
1787 1788
	 *
	 * containingBd 为父类bean,对顶层元素的解析应设置为null
C
congshuo_cnki 已提交
1789 1790 1791
	 */
	@Nullable
	public BeanDefinition parseCustomElement(Element ele, @Nullable BeanDefinition containingBd) {
1792
		System.out.println("==================处理自定义bean=====================");
C
congshuo_cnki 已提交
1793
		String namespaceUri = getNamespaceURI(ele);
1794
		System.err.println("获取对应的命名空间:" + namespaceUri);
C
congshuo_cnki 已提交
1795 1796 1797
		if (namespaceUri == null) {
			return null;
		}
1798
		/** 根据命名空间找到对应的NamespaceHandler*/
C
congshuo_cnki 已提交
1799
		NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
C
congshuo_cnki 已提交
1800
		System.err.println("根据命名空间找到对应的NamespaceHandler" + handler.toString());
C
congshuo_cnki 已提交
1801 1802 1803 1804
		if (handler == null) {
			error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
			return null;
		}
1805
		/** 调用自定义的NamespaceHandler进行解析*/
C
congshuo_cnki 已提交
1806 1807 1808 1809 1810 1811 1812 1813 1814 1815
		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) {
1816
		/**
C
congshuo_cnki 已提交
1817
		 * 第三个参数是父类的bean,当对某个嵌套配置进行分析时,这里需要传父类的beanDefinition,这里传入的参数
1818 1819
		 * 其实是为了使用父类的scope属性,以备若子类没有配置scope时使用父类的属性,这里是顶层配置所以传null
		 */
C
congshuo_cnki 已提交
1820 1821
		System.out.println("第三个参数是父类的bean,当对某个嵌套配置进行分析时,这里需要传父类的beanDefinition,这里传入的参数\n" +
				"其实是为了使用父类的scope属性,以备若子类没有配置scope时使用父类的属性,这里是顶层配置所以传null");
C
congshuo_cnki 已提交
1822
		return decorateBeanDefinitionIfRequired(ele, originalDef, null);
1823

C
congshuo_cnki 已提交
1824 1825 1826 1827 1828 1829 1830 1831
	}

	/**
	 * 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
1832 1833 1834 1835
	 *
	 * 对于程序默认的标签的处理其实是直接略过的,因为默认的标签这里已经被处理完了,这里只对自定义
	 * 的标签或者说对bean的自定义属性感兴趣.在方法中实现了寻找自定义标签并根据自定义标签寻找命名
	 * 空间处理器.
C
congshuo_cnki 已提交
1836 1837 1838 1839 1840 1841 1842 1843
	 */
	public BeanDefinitionHolder decorateBeanDefinitionIfRequired(
			Element ele, BeanDefinitionHolder originalDef, @Nullable BeanDefinition containingBd) {

		BeanDefinitionHolder finalDefinition = originalDef;

		// Decorate based on custom attributes first.
		NamedNodeMap attributes = ele.getAttributes();
1844
		/** 遍历所有的属性,看看是否有适用于修饰的属性*/
C
congshuo_cnki 已提交
1845
		System.err.println("遍历所有的属性,看看是否有适用于修饰的属性");
C
congshuo_cnki 已提交
1846 1847
		for (int i = 0; i < attributes.getLength(); i++) {
			Node node = attributes.item(i);
C
congshuo_cnki 已提交
1848
			System.out.println(node.toString());
C
congshuo_cnki 已提交
1849 1850 1851 1852 1853
			finalDefinition = decorateIfRequired(node, finalDefinition, containingBd);
		}

		// Decorate based on custom nested elements.
		NodeList children = ele.getChildNodes();
1854
		/** 遍历所有的子节点,看看是否有适用于修饰的子元素*/
C
congshuo_cnki 已提交
1855 1856 1857 1858 1859 1860
		for (int i = 0; i < children.getLength(); i++) {
			Node node = children.item(i);
			if (node.getNodeType() == Node.ELEMENT_NODE) {
				finalDefinition = decorateIfRequired(node, finalDefinition, containingBd);
			}
		}
C
congshuo_cnki 已提交
1861

C
congshuo_cnki 已提交
1862 1863 1864 1865 1866 1867 1868 1869 1870 1871
		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
1872 1873 1874
	 *
	 * 首先获取属性或者元素命名空间,以此来判断元素或者属性是否适用于自定义标签的解析条件,找出
	 * 自定义类型所对应的NamespaceHandler并进行进一步解析,
C
congshuo_cnki 已提交
1875 1876 1877 1878
	 */
	public BeanDefinitionHolder decorateIfRequired(
			Node node, BeanDefinitionHolder originalDef, @Nullable BeanDefinition containingBd) {

1879
		/** 获取自定义名称的命名空间*/
C
congshuo_cnki 已提交
1880
		String namespaceUri = getNamespaceURI(node);
C
congshuo_cnki 已提交
1881
		System.err.println("获取自定义名称的命名空间:" + namespaceUri);
1882
		/** 对于非默认标签进行修饰*/
C
congshuo_cnki 已提交
1883
		System.err.println("对于非默认标签进行修饰");
C
congshuo_cnki 已提交
1884
		if (namespaceUri != null && !isDefaultNamespace(namespaceUri)) {
1885
			/** 根据默认命名空间找到对应的处理器*/
C
congshuo_cnki 已提交
1886
			System.err.println("根据默认命名空间找到对应的处理器");
C
congshuo_cnki 已提交
1887
			NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
C
congshuo_cnki 已提交
1888
			System.err.println("NamespaceHandler: " +handler.toString());
C
congshuo_cnki 已提交
1889
			if (handler != null) {
1890
                /** 进行修饰*/
C
congshuo_cnki 已提交
1891
				System.err.println("进行修饰");
C
congshuo_cnki 已提交
1892 1893
				BeanDefinitionHolder decorated =
						handler.decorate(node, originalDef, new ParserContext(this.readerContext, this, containingBd));
C
congshuo_cnki 已提交
1894
				System.err.println("BeanDefinitionHolder: " + decorated.toString());
C
congshuo_cnki 已提交
1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937 1938 1939 1940 1941 1942 1943 1944 1945 1946 1947 1948 1949 1950 1951 1952 1953 1954 1955 1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974
				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 <property>.", 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.
	 * <p>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}.
	 * <p>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.
	 * <p>The default implementation checks the supplied desired name against both
	 * {@link Node#getNodeName()} and {@link Node#getLocalName()}.
	 * <p>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.
1975
	 * 确定给定节点是否指示默认命名空间。
C
congshuo_cnki 已提交
1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989
	 */
	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())));
	}

}