加载xml文件

整体流程

1、封装xml文件尾Resource对象,构造BeanFactory对象

2、进入BeanFactory构造函数,调用XmlBeanDefinitionReader的loadBeanDefinitions去读取Resource

2.1、Resource会在loadBeanDefinitions中被封装为EncodedResource

2.2、loadBeanDefinitions中会对EncodedResource加入到ThreadLocal当前线程中,加入成功则会将EncodedResource封装为InputSource

2.3、对InputSource进行doLoadBeanDefinitions操作

2.4、将Xml配置文件通过doLoadDocument读取得到Document对象

2.5、通过registerBeanDefinitions将Document对象转换为BeanDefinitions注册到注册中心

2.5.1、实例化BeanDefinitionDocumentReader去读取Document

2.5.2、beanDefinitionDocumentReader.registerBeanDefinitions去将Document中的BeanDefinitions注册到注册中心

2.6、返回注册成功的BeanDefinition数量

springboot xml请求入参判空 spring加载xml_加载

源码解析

public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException {
		super(parentBeanFactory);
		this.reader.loadBeanDefinitions(resource);
	}
@Override
	public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
		//1、将resource包装成带编码格式的EncodedResource
		//2、重载调用loadBeanDefinitions
		return loadBeanDefinitions(new EncodedResource(resource));
	}
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
		Assert.notNull(encodedResource, "EncodedResource must not be null");
		if (logger.isTraceEnabled()) {
			logger.trace("Loading XML bean definitions from " + encodedResource);
		}

		//拿到当前线程已经加载过的所有encodedResource
		Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();

		//将当前的encodedResource加入到threadLocal-set中,加入失败,说明当前encodedResource已经加载过了,不能重复加载
		if (!currentResources.add(encodedResource)) {
			throw new BeanDefinitionStoreException(
					"Detected cyclic loading of " + encodedResource + " - check your import definitions!");
		}

		//拿到encodedResource包装的输入流对象
		try (InputStream inputStream = encodedResource.getResource().getInputStream()) {
			//因为接下来 要使用sax解析器 解析xml,所以需要输入流包装成inputSource,inputSource是sax中表示资源的对象。
			InputSource inputSource = new InputSource(inputStream);

			//条件成立说明encodedSource是需要设置编码格式的,也需要将sax中表示资源对象的格式设置为对应的编码
			if (encodedResource.getEncoding() != null) {
				inputSource.setEncoding(encodedResource.getEncoding());
			}
			//加载beanDefinition的入口
			return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
		}
		catch (IOException ex) {
			throw new BeanDefinitionStoreException(
					"IOException parsing XML document from " + encodedResource.getResource(), ex);
		}
		finally {
			//当前线程加载完资源后,需要把资源移除出去。因为当前资源已经加载完成了。
			//因为resourcesCurrentlyBeingLoaded表示当前线程正在加载的resource,执行到这里,就已经处理完成了。
			//需要从set中移除
			currentResources.remove(encodedResource);
			//注意:这里是防止threadlocal内存泄露
			if (currentResources.isEmpty()) {
				this.resourcesCurrentlyBeingLoaded.remove();
			}
		}
	}
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
			throws BeanDefinitionStoreException {

		try {
			//将resource转换成程序层面可以识别的有层次结构的document对象。
			Document doc = doLoadDocument(inputSource, resource);
			//将document解析成bd,并且注册到beanfactory中,最终返回新注册到bf的bd数量。
			int count = registerBeanDefinitions(doc, resource);
			if (logger.isDebugEnabled()) {
				logger.debug("Loaded " + count + " bean definitions from " + resource);
			}
			//返回新注册的bd的数量
			return count;
		}
		catch (BeanDefinitionStoreException ex) {
			throw ex;
		}
		catch (SAXParseException ex) {
			throw new XmlBeanDefinitionStoreException(resource.getDescription(),
					"Line " + ex.getLineNumber() + " in XML document from " + resource + " is invalid", ex);
		}
		catch (SAXException ex) {
			throw new XmlBeanDefinitionStoreException(resource.getDescription(),
					"XML document from " + resource + " is invalid", ex);
		}
		catch (ParserConfigurationException ex) {
			throw new BeanDefinitionStoreException(resource.getDescription(),
					"Parser configuration exception parsing XML from " + resource, ex);
		}
		catch (IOException ex) {
			throw new BeanDefinitionStoreException(resource.getDescription(),
					"IOException parsing XML document from " + resource, ex);
		}
		catch (Throwable ex) {
			throw new BeanDefinitionStoreException(resource.getDescription(),
					"Unexpected exception parsing XML document from " + resource, ex);
		}
	}
protected Document doLoadDocument(InputSource inputSource, Resource resource) throws Exception {
		return this.documentLoader.loadDocument(inputSource, getEntityResolver(), this.errorHandler,
				getValidationModeForResource(resource), isNamespaceAware());
	}
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
		//创建一个BeanDefinitionDocumentReader 每个document对象都会创建一个BeanDefinitionDocumentReader对象
		BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
		//getRegistry()会返回程序创建的beanFactory实例。countBefore:解析该doc之前,bf中已经有的bd数量
		int countBefore = getRegistry().getBeanDefinitionCount();
		//解析doc并且注册到beanFactory中
		//xmlReaderContext:包含最主要的参数 : 当前 this -> XmlBeanDefinitionReafer -> beanFactory
		//因此可以把doc解析出来的bd放到beanFactory中
		documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
		//返回的新注册的bd数量
		return getRegistry().getBeanDefinitionCount() - countBefore;
	}

解析Document

时序图

springboot xml请求入参判空 spring加载xml_java_02

源码解析
documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
protected void doRegisterBeanDefinitions(Element root) {
		// Any nested <beans> elements will cause recursion in this method. In
		// order to propagate and preserve <beans> default-* attributes correctly,
		// keep track of the current (parent) delegate, which may be null. Create
		// the new (child) delegate with a reference to the parent for fallback purposes,
		// then ultimately reset this.delegate back to its original (parent) reference.
		// this behavior emulates a stack of delegates without actually necessitating one.
		BeanDefinitionParserDelegate parent = this.delegate;
		//返回一个bd的解析器代表
		this.delegate = createDelegate(getReaderContext(), root, parent);
		//一般情况下条件成立
		if (this.delegate.isDefaultNamespace(root)) {
			//获取beans标签上的标签属性profile
			String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
			//条件成立:说明beans标签上有profile 属性 有值
			if (StringUtils.hasText(profileSpec)) {
				//将profile按照 ,; 拆分成字符串数组
				String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
						profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
				// We cannot use Profiles.of(...) since profile expressions are not supported
				// in XML config. See SPR-12458 for details.
				//!条件:true不解析,false继续解析
				if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
					if (logger.isDebugEnabled()) {
						logger.debug("Skipped XML bean definition file due to specified profiles [" + profileSpec +
								"] not matching: " + getReaderContext().getResource());
					}
					return;
				}
			}
		}

		//子类扩张的地方
		preProcessXml(root);
		//解析<beans>标签
		parseBeanDefinitions(root, this.delegate);
		//子类扩张的地方
		postProcessXml(root);
		
		this.delegate = parent;
	}

parseBeanDefinitions流程

源码解析

来到XmlBeanDefinitionReader#registerBeanDefinitions方法,执行documentReader.registerBeanDefinitions(doc, createReaderContext(resource));逻辑,该逻辑是注册BeanDefinition的入口。

public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
		//创建一个BeanDefinitionDocumentReader 每个document对象都会创建一个BeanDefinitionDocumentReader对象
		BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
		//getRegistry()会返回程序创建的beanFactory实例。countBefore:解析该doc之前,bf中已经有的bd数量
		int countBefore = getRegistry().getBeanDefinitionCount();
		//解析doc并且注册到beanFactory中
		//xmlReaderContext:包含最主要的参数 : 当前 this -> XmlBeanDefinitionReafer -> beanFactory
		//因此可以把doc解析出来的bd放到beanFactory中
		documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
		//返回的新注册的bd数量
		return getRegistry().getBeanDefinitionCount() - countBefore;
	}

进入正式解析BeanDefinition逻辑doRegisterBeanDefinitions

@Override
	public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
		//先把上下文对象保存到reader的字段中
		this.readerContext = readerContext;
		//doc.getDocumentElement() =》 拿出document代表的xml的顶级标签 => <beans> ... <beans/>
		doRegisterBeanDefinitions(doc.getDocumentElement());
	}

进入parseBeanDefinitions(root, this.delegate);逻辑,解析beans

protected void doRegisterBeanDefinitions(Element root) {
		// Any nested <beans> elements will cause recursion in this method. In
		// order to propagate and preserve <beans> default-* attributes correctly,
		// keep track of the current (parent) delegate, which may be null. Create
		// the new (child) delegate with a reference to the parent for fallback purposes,
		// then ultimately reset this.delegate back to its original (parent) reference.
		// this behavior emulates a stack of delegates without actually necessitating one.
		BeanDefinitionParserDelegate parent = this.delegate;
		//返回一个bd的解析器代表
		this.delegate = createDelegate(getReaderContext(), root, parent);
		//一般情况下条件成立
		if (this.delegate.isDefaultNamespace(root)) {
			//获取beans标签上的标签属性profile
			String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
			//条件成立:说明beans标签上有profile 属性 有值
			if (StringUtils.hasText(profileSpec)) {
				//将profile按照 ,; 拆分成字符串数组
				String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
						profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
				// We cannot use Profiles.of(...) since profile expressions are not supported
				// in XML config. See SPR-12458 for details.
				//!条件:true不解析,false继续解析
				if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
					if (logger.isDebugEnabled()) {
						logger.debug("Skipped XML bean definition file due to specified profiles [" + profileSpec +
								"] not matching: " + getReaderContext().getResource());
					}
					return;
				}
			}
		}

		//子类扩张的地方
		preProcessXml(root);
		//解析<beans>标签
		parseBeanDefinitions(root, this.delegate);
		//子类扩张的地方
		postProcessXml(root);

		this.delegate = parent;
	}

parseBeanDefinitions:解析自定义标签和spring默认标签,我们主要看的是parseDefaultElement如何去解析spring的默认标签

protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
		//条件成立:说明root是spring的命名空间
		if (delegate.isDefaultNamespace(root)) {
			//<beans>
			//	<bean></bean>
			//	<bean></bean>
			//	<bean></bean>
			//</beans>
			NodeList nl = root.getChildNodes();
			//迭代每一个子标签
			for (int i = 0; i < nl.getLength(); i++) {
				//node:子标签
				Node node = nl.item(i);
				if (node instanceof Element) {
					//条件成立:说明子标签也是spring默认标签
					Element ele = (Element) node;
					if (delegate.isDefaultNamespace(ele)) {
						parseDefaultElement(ele, delegate);
					}
					//条件不成立:说明子标签是自定义标签
					else {
						delegate.parseCustomElement(ele);
					}
				}
			}
		}
		//解析自定义标签的逻辑
		else {
			delegate.parseCustomElement(root);
		}
	}

使用委托者去解析各个spring中的默认标签,我们主要看的是bean标签,也就是processBeanDefinition的逻辑

private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
		//条件成立:说明ele标签是import标签
		if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
			importBeanDefinitionResource(ele);
		}
		//条件成立:说明ele标签是别名标签
		else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
			processAliasRegistration(ele);
		}
		//条件成立:说明ele标签是bean标签
		else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
			processBeanDefinition(ele, delegate);
		}
		//条件成立:说明ele标签是 嵌套 beans标签
		else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
			// recurse
			doRegisterBeanDefinitions(ele);
		}
	}

解析完成BeanDefinition,并且装饰后,注入到注册中心。我们看看如何进行对bean标签的解析,也就是parseBeanDefinitionElement的逻辑

protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
		//解析完成后,返回bdHold,保存了bean标签上的别名信息和BeanDefinition
		BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
		if (bdHolder != null) {
			//装饰BeanDefinition,主要是处理自定义属性
			bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
			try {
				// Register the final decorated instance.
				//将BeanDefinition注册到容器中
				BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
			}
			catch (BeanDefinitionStoreException ex) {
				getReaderContext().error("Failed to register bean definition with name '" +
						bdHolder.getBeanName() + "'", ele, ex);
			}
			// Send registration event.
			//发送bd注册完成的事情
			getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
		}
	}
解析的核心流程
@Nullable
	public BeanDefinitionHolder parseBeanDefinitionElement(Element ele) {
		return parseBeanDefinitionElement(ele, null);
	}
@Nullable
	public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) {
		//获取bean标签id属性值
		String id = ele.getAttribute(ID_ATTRIBUTE);
		//获取bean标签name属性值
		String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
		//别名列表
		List<String> aliases = new ArrayList<>();

		if (StringUtils.hasLength(nameAttr)) {
			//将name属性值按照,;拆分成数组
			String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
			//保存到别名数组
			aliases.addAll(Arrays.asList(nameArr));
		}
		//默认情况beanName为id
		String beanName = id;
		//条件1成立:说明id为空
		//条件2处理:说明别名信息List有值
		if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {
			//那别名的第一个值当做是beanName
			beanName = aliases.remove(0);
			if (logger.isTraceEnabled()) {
				logger.trace("No XML 'id' specified - using '" + beanName +
						"' as bean name and " + aliases + " as aliases");
			}
		}

		if (containingBean == null) {
			checkNameUniqueness(beanName, aliases, ele);
		}

		//核心逻辑:将ele标签解析成BeanDefinition
		AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);

		//条件成立:说明ele被解析成立BeanDefinition对象
		if (beanDefinition != null) {
			//条件成立:说明没有传入id和name,需要生成beanName
			if (!StringUtils.hasText(beanName)) {

				try {
					if (containingBean != null) {
						beanName = BeanDefinitionReaderUtils.generateBeanName(
								beanDefinition, this.readerContext.getRegistry(), true);
					}

					else {
						//生成className+序列号作为名称
						//如:demo0#0
						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.
						//拿到bd对呀的className
						String beanClassName = beanDefinition.getBeanClassName();
						//条件1:一般成立
						//条件2:一般成立
						//条件3:一般成立
						//条件4:判断BeanClassName是否被使用,成立说明没有被使用,这个时候给当前beanDefinition一个叫做beanClassName的别名
						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);
			//将BeanDefinition和benaName和别名保证到BeanDefinitionHolder中
			return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
		}

		return null;
	}

解析子标签和属性

@Nullable
	public AbstractBeanDefinition parseBeanDefinitionElement(
			Element ele, String beanName, @Nullable BeanDefinition containingBean) {
		//表示当前解析器的状态,因为接下来要解析bean标签,所以设置为了BeanEntry状态
		this.parseState.push(new BeanEntry(beanName));


		String className = null;
		//一般情况 bean 标签 都保护class属性,除非bean标签作为parent标签被子标签继承时,class属性才为null
		if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
			//获取bean标签className
			className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
		}

		String parent = null;
		//bean标签可以继承parent标签,类似 子类 继承 父类,一般很少用到
		if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
			parent = ele.getAttribute(PARENT_ATTRIBUTE);
		}

		try {
			//创建了benaDefinition对象,仅仅设置了class信息
			AbstractBeanDefinition bd = createBeanDefinition(className, parent);

			//解析bean标签下的属性
			parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);

			//<bean>
			// 		<description>xxxx</description>
			// </bean>
			//将description标签中的信息保存到benaDefinition中
			bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));

			//<bean>
			// 		<mate key="mate_1" value="mate_1_value"></mate>
			// 		<mate key="mate_2" value="mate_2_value"></mate>
			// </bean>
			//解析mate标签
			parseMetaElements(ele, bd);


			//解析lookup-method:lookup-method主要是动态代理返回对应的指定bean
			//bd中保存了需要methodOverrides
			parseLookupOverrideSubElements(ele, bd.getMethodOverrides());

			//解析replace-method:replace-method主要是动态代理为指定方法
			parseReplacedMethodSubElements(ele, bd.getMethodOverrides());

			//解析构造方法参数子标签
			parseConstructorArgElements(ele, bd);

			//解析属性子标签
			parsePropertyElements(ele, bd);

			//解析qualifer子标签:匹配到多个bean的时候,可以使用qualifer来指定bean
			parseQualifierElements(ele, bd);


			bd.setResource(this.readerContext.getResource());
			bd.setSource(extractSource(ele));

			return bd;
		}
		catch (ClassNotFoundException ex) {
			error("Bean class [" + className + "] not found", ele, ex);
		}
		catch (NoClassDefFoundError err) {
			error("Class that bean class [" + className + "] depends on not found", ele, err);
		}
		catch (Throwable ex) {
			error("Unexpected failure during bean definition parsing", ele, ex);
		}
		finally {
			this.parseState.pop();
		}

		return null;
	}

解析属性逻辑

public AbstractBeanDefinition parseBeanDefinitionAttributes(Element ele, String beanName,
			@Nullable BeanDefinition containingBean, AbstractBeanDefinition bd) {

		//条件成立:说明bean标签有singleton属性,这个属性过期了,给一个错误
		if (ele.hasAttribute(SINGLETON_ATTRIBUTE)) {
			error("Old 1.x 'singleton' attribute in use - upgrade to 'scope' declaration", ele);
		}
		//条件成立:说明bean标签存在一个scope属性。scope默认值是singleton
		else if (ele.hasAttribute(SCOPE_ATTRIBUTE)) {
			//读取scope设置到bd中
			bd.setScope(ele.getAttribute(SCOPE_ATTRIBUTE));
		}
		else if (containingBean != null) {
			// Take default from containing bean in case of an inner bean definition.
			bd.setScope(containingBean.getScope());
		}

		//<bean abstract="true"></bean>
		//条件成立:说明bean是一个抽象标签,只能作为父标签存在,让子标签去继承
		if (ele.hasAttribute(ABSTRACT_ATTRIBUTE)) {
			bd.setAbstract(TRUE_VALUE.equals(ele.getAttribute(ABSTRACT_ATTRIBUTE)));
		}

		//读取bean标签上的lazy-init属性
		String lazyInit = ele.getAttribute(LAZY_INIT_ATTRIBUTE);
		//条件成立:说明lazyInit为空或者是default
		if (isDefaultValue(lazyInit)) {
			//获取默认值。默认是false
			lazyInit = this.defaults.getLazyInit();
		}
		bd.setLazyInit(TRUE_VALUE.equals(lazyInit));


		//获取bean标签上的autowire属性值
		String autowire = ele.getAttribute(AUTOWIRE_ATTRIBUTE);
		//转为成int值后,设置到bd中
		bd.setAutowireMode(getAutowireMode(autowire));

		//<bean depends-on="a,b"></bean>,说明bean实例化时需要先处理a,b
		//条件成立:存在depends-on属性
		if (ele.hasAttribute(DEPENDS_ON_ATTRIBUTE)) {
			String dependsOn = ele.getAttribute(DEPENDS_ON_ATTRIBUTE);
			bd.setDependsOn(StringUtils.tokenizeToStringArray(dependsOn, MULTI_VALUE_ATTRIBUTE_DELIMITERS));
		}

		//读取bean标签autowire-candidate属性,设置了bean的autowire-candidate为false后,则当前bean不参与其他bean的自动依赖注入。
		// (场景在于多个实现了同一个接口的bean要注入到某个bean的时候,指定不参与)
		//autowireCandidate默认值是true,表示参与外部的注入
		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 {
			//配置了autowire-candidate
			bd.setAutowireCandidate(TRUE_VALUE.equals(autowireCandidate));
		}

		//当某个接口有多个实现对象时,外部spring对象依赖该接口时,可以给该接口指定的实现对象
		if (ele.hasAttribute(PRIMARY_ATTRIBUTE)) {
			bd.setPrimary(TRUE_VALUE.equals(ele.getAttribute(PRIMARY_ATTRIBUTE)));
		}

		//当spring创建该bean对应的实例的时候,最终会执行init-method方法
		if (ele.hasAttribute(INIT_METHOD_ATTRIBUTE)) {
			String initMethodName = ele.getAttribute(INIT_METHOD_ATTRIBUTE);
			bd.setInitMethodName(initMethodName);
		}
		else if (this.defaults.getInitMethod() != null) {
			bd.setInitMethodName(this.defaults.getInitMethod());
			bd.setEnforceInitMethod(false);
		}


		//当spring容器销毁的时候,执行spring容器内管理的销毁方法
		if (ele.hasAttribute(DESTROY_METHOD_ATTRIBUTE)) {
			String destroyMethodName = ele.getAttribute(DESTROY_METHOD_ATTRIBUTE);
			bd.setDestroyMethodName(destroyMethodName);
		}
		else if (this.defaults.getDestroyMethod() != null) {
			bd.setDestroyMethodName(this.defaults.getDestroyMethod());
			bd.setEnforceDestroyMethod(false);
		}


		//读取factory-method属性
		if (ele.hasAttribute(FACTORY_METHOD_ATTRIBUTE)) {
			bd.setFactoryMethodName(ele.getAttribute(FACTORY_METHOD_ATTRIBUTE));
		}

		//读取factory-bean属性
		if (ele.hasAttribute(FACTORY_BEAN_ATTRIBUTE)) {
			bd.setFactoryBeanName(ele.getAttribute(FACTORY_BEAN_ATTRIBUTE));
		}

		return bd;
	}
小结

spring对于xml文件的的解析比较复杂,不要太过于深入,知道整体的流程就差不多了