文档章节

Spring源码分析,BeanDefinition加载过程

 慕哲
发布于 2017/04/25 10:44
字数 7366
阅读 204
收藏 1

1.简介

Spring的启动分为关键步骤,首先是将配置文件中定义的<bean>信息加载到BeanDefintionRegistry中。然后通过BeanFactory中的getBean方法来将BeanDefinition进行实例化,开始整个bean的生命周期。

2.BeanDefinitionReader

public interface BeanDefinitionReader {
	BeanDefinitionRegistry getRegistry();//获取到对应的BeanDefinitionRegistry
	ResourceLoader getResourceLoader();//获取到ResourceLoader,为了获取对应的Resource,可以认为是一个工厂方法。
	ClassLoader getBeanClassLoader();//获取ClassLoader
	BeanNameGenerator getBeanNameGenerator();//获取到BeanName的命名
	int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException;//将Resource中的Bean加载到BeanRegistry中来。
	int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException;
	int loadBeanDefinitions(String location) throws BeanDefinitionStoreException;//将localtions对应的文件中定义的BeanDefinition加载并注册到BeanRegistry中来。
	int loadBeanDefinitions(String... locations) throws BeanDefinitionStoreException;
}

BeanDefinitionReader依赖了ResourceLoader,BeanDefinitionRegistry,Resource这些关键类。从接口看来loadBeanDefintions()方法,主要是将Resource中定义的Bean对象加载到BeanDefinitionRegistry中来。

3.BeanDefinition的加载过程

4.关键代码阅读

4.1 protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource) throws BeanDefinitionStoreException 

当前方法首先是对resource中定义的Document进行加载,校验,解析为一个Document对象。然后通过registerBeanDefinitions(doc,resource)将当前Document中的bean加载到BeanDefinitionRegistry中来。

protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
			throws BeanDefinitionStoreException {
		try {
			Document doc = doLoadDocument(inputSource, resource);//这个过程当中主要是对当前的xml文件进行解析,校验,获取到对应的Document的对象。
			return registerBeanDefinitions(doc, resource);//这个方法是关键
		}
		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);
		}
	}

 

  4.2registerBeanDefinitions(doc, resource)

主要是讲doc中定义的<bean>等相关的信息加载到BeanDefinitionRegistry。

public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
		BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();//第一步创建BeanDefinitionDocumentReader。这个是一个BeanDefinition的从Document读取的Reader。
		int countBefore = getRegistry().getBeanDefinitionCount();
		documentReader.registerBeanDefinitions(doc, createReaderContext(resource));//通过BeanDefinitionDocumentReader的registerBeanDefinitions(doc, createReaderContext(resource))方法将Document中定义的Bean注册到registry中去。
		return getRegistry().getBeanDefinitionCount() - countBefore;
	}

当前方法将加载的任务委托给了 BeanDefinitionDocumentReader中的registerBeanDefinitions(doc, createReaderContext(resource))方法。

public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
		this.readerContext = readerContext;
		logger.debug("Loading bean definitions");
		Element root = doc.getDocumentElement();
		doRegisterBeanDefinitions(root);
	}

4.3BeanDefinitionDocumentReader.doRegisterBeanDefinitions(Element root)

看下如何实现的:

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;
		this.delegate = createDelegate(getReaderContext(), root, parent);//创建BeanDefinitionParseDelegate,其中对于lazy-init。auto-wire中相关的全局的默认的设置。

		if (this.delegate.isDefaultNamespace(root)) {
			String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
			if (StringUtils.hasText(profileSpec)) {
				String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
						profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
				if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
					if (logger.isInfoEnabled()) {
						logger.info("Skipped XML bean definition file due to specified profiles [" + profileSpec +
								"] not matching: " + getReaderContext().getResource());
					}
					return;
				}
			}
		}

		preProcessXml(root);
		parseBeanDefinitions(root, this.delegate);
		postProcessXml(root);

		this.delegate = parent;
	}

4.4 parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate)

protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
		if (delegate.isDefaultNamespace(root)) {
			NodeList nl = root.getChildNodes();
			for (int i = 0; i < nl.getLength(); i++) {
				Node node = nl.item(i);
				if (node instanceof Element) {
					Element ele = (Element) node;
					if (delegate.isDefaultNamespace(ele)) {
						parseDefaultElement(ele, delegate);//这个是Spring中定义的Element的实现。
					}
					else {
						delegate.parseCustomElement(ele);
					}
				}
			}
		}
		else {
			delegate.parseCustomElement(root);//用户自定义的Element类型。这里先按下不表。
		}
	}

以上方法,对于xml中定义的有Spring中默认定义的标签,也有用户自定义的标签。这里重点看下Spring自定义的标签。

4.5 parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate)

看下是如何注册 系统中定义的Element的。这里是如何将Element转变为BeanRegistry中定义的BeanDefinition或者是其他相关的辅助内容的?这里是关键。

private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
		if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {//处理import文件。
			importBeanDefinitionResource(ele);
		}
		else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {//这里是 alias处理的别名
			processAliasRegistration(ele);
		}
		else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {//这里是<bean>,这个是重点关注的。
			processBeanDefinition(ele, delegate);
		}
		else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {//这个是嵌套的<beans>.
			// recurse
			doRegisterBeanDefinitions(ele);
		}
	}

这里重点看下是如何解析<bean> 的。

4.6 processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate)

protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
		BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);//这里是讲一个element转变为一个BeanDefinitionHolder、
		if (bdHolder != null) {
			bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);//BeanDefinition的额外的解析工作。
			try {
				// Register the final decorated instance.
				BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());//将BeanDefinitionHolder注册到BeanDefinitionRegistry中去。
			}
			catch (BeanDefinitionStoreException ex) {
				getReaderContext().error("Failed to register bean definition with name '" +
						bdHolder.getBeanName() + "'", ele, ex);
			}
			// Send registration event.
			getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));//发布一下创建的成功的事件。
		}
	}

从上面的代码可见,将一个<bean>转变为注册为注册在BeanDefinitionRegitry中的GenericBeanDefinition主要有以上的几个步骤:

第一步:通过 parseBeanDefinitionElement(ele) 将当前的<bean>转变为一个BeanDefinitionHolder。其中包括了 beanName,aliasName和GenericBeanDefinition。

第二步:通过decorateBeanDefinitionIfRequired(ele, bdHolder)方法对于BeanDefinitionHolder进行额外的处理,主要是对于<bean>中用户自定义的一些标签。

第三步:通过BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry())将当前的BeanDefinitionHolder对象注册到目标BeanDefinitionRegistry中去。

第四步:将注册完成的事件发布一下事件。

 

4.6.1  parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) 

看下public BeanDefinitionHolder parseBeanDefinitionElement(Element ele) 方法,是调用了BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean)。
看下具体实现,由于<bean>配置比较的复制,可能会有省略。

public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) {
		String id = ele.getAttribute(ID_ATTRIBUTE);
		String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);

		List<String> aliases = new ArrayList<String>();
		if (StringUtils.hasLength(nameAttr)) {
			String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
			aliases.addAll(Arrays.asList(nameArr));
		}

		String beanName = id;
		if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {
			beanName = aliases.remove(0);
			if (logger.isDebugEnabled()) {
				logger.debug("No XML 'id' specified - using '" + beanName +
						"' as bean name and " + aliases + " as aliases");
			}
		}

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

		AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
		if (beanDefinition != null) {
			if (!StringUtils.hasText(beanName)) {
				try {
					if (containingBean != null) {
						beanName = BeanDefinitionReaderUtils.generateBeanName(
								beanDefinition, this.readerContext.getRegistry(), true);
					}
					else {
						beanName = this.readerContext.generateBeanName(beanDefinition);
						// Register an alias for the plain bean class name, if still possible,
						// if the generator returned the class name plus a suffix.
						// This is expected for Spring 1.2/2.0 backwards compatibility.
						String beanClassName = beanDefinition.getBeanClassName();
						if (beanClassName != null &&
								beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() &&
								!this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {
							aliases.add(beanClassName);
						}
					}
					if (logger.isDebugEnabled()) {
						logger.debug("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;
	}

4.6.1.1 确定beanName

确定当前的beanName和alias:首先是beanName =  id。alias = name中以“,;”分割的字符串。如果id为空,就一alias种第一个为beanName,剩余的为alias。

4.6.1.2 判断bean是否唯一

判断beanName是否被使用过。如果使用过就报错,这里对于错误的处理是值得看下的:

protected void error(String message, Element source) {
		this.readerContext.error(message, source, this.parseState.snapshot());
	}

在当前的类中有一个统一的error的方法,然后想对于异常信息的处理交给ReaderContext的error()去统一处理。这样相对比较的灵活,如果是直接抛出异常反而没有这种方式好。当然error方法最终一定要打断当前的执行进程的。

4.6.1.3 开始解析  BeanDefinition对象

AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean)。

public AbstractBeanDefinition parseBeanDefinitionElement(
			Element ele, String beanName, BeanDefinition containingBean) {

		this.parseState.push(new BeanEntry(beanName));

		String className = null;
		if (ele.hasAttribute(CLASS_ATTRIBUTE)) {//开始处理class标签
			className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
		}

		try {
			String parent = null;//看下有没有parenet的实现。
			if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
				parent = ele.getAttribute(PARENT_ATTRIBUTE);
			}
			AbstractBeanDefinition bd = createBeanDefinition(className, parent);//创建GenericBeanDefinition对象,主要设置parentClassName和ClassName。如果指定了ClassLoader,就将当前的class进行加载进来。

			parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);//解析BeanDefinition中Attribute、
			bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));//设置一下description的实现。

			parseMetaElements(ele, bd);//meta属性Element
			parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
			parseReplacedMethodSubElements(ele, bd.getMethodOverrides());

			parseConstructorArgElements(ele, bd);
			parsePropertyElements(ele, bd);
			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;
	}

看一下 在<bean>中定义的Attribute是如何解析的。这些都是定义在<bean>中的attribute,这些并不太复杂。

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

		if (ele.hasAttribute(SINGLETON_ATTRIBUTE)) {//如果属性中有sigleton,这个时候就报错。
			error("Old 1.x 'singleton' attribute in use - upgrade to 'scope' declaration", ele);
		}
		else if (ele.hasAttribute(SCOPE_ATTRIBUTE)) {//设置scope。
			bd.setScope(ele.getAttribute(SCOPE_ATTRIBUTE));
		}
		else if (containingBean != null) {//如果containBean不为空,就设置对象的scope为最新的scope。
			// Take default from containing bean in case of an inner bean definition.
			bd.setScope(containingBean.getScope());
		}

		if (ele.hasAttribute(ABSTRACT_ATTRIBUTE)) {//设置当前对象为abstract对象。
			bd.setAbstract(TRUE_VALUE.equals(ele.getAttribute(ABSTRACT_ATTRIBUTE)));
		}

		String lazyInit = ele.getAttribute(LAZY_INIT_ATTRIBUTE);//设置lazy-init属性。
		if (DEFAULT_VALUE.equals(lazyInit)) {
			lazyInit = this.defaults.getLazyInit();
		}
		bd.setLazyInit(TRUE_VALUE.equals(lazyInit));

		String autowire = ele.getAttribute(AUTOWIRE_ATTRIBUTE);//设置自动装配属性。		bd.setAutowireMode(getAutowireMode(autowire));

		String dependencyCheck = ele.getAttribute(DEPENDENCY_CHECK_ATTRIBUTE);//设置  依赖自动检查
		bd.setDependencyCheck(getDependencyCheck(dependencyCheck));

		if (ele.hasAttribute(DEPENDS_ON_ATTRIBUTE)) {//设置依赖属性
			String dependsOn = ele.getAttribute(DEPENDS_ON_ATTRIBUTE);
			bd.setDependsOn(StringUtils.tokenizeToStringArray(dependsOn, MULTI_VALUE_ATTRIBUTE_DELIMITERS));
		}

		//设置 Autowire_Candidate_attribure属性,如果这个属性设置为false,这个对象将不会作为被自动装配的对象。
		//首先会使用全局的autowire_candidate_attribute的属性,然后看当前<bean>中的设置,当前<bean>中设置的优先级更高。
		String autowireCandidate = ele.getAttribute(AUTOWIRE_CANDIDATE_ATTRIBUTE);
		if ("".equals(autowireCandidate) || DEFAULT_VALUE.equals(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));//
		}

		//当自动装配的时候,出现多个候选Bean的时候,被标记了primary属性的将会被优先的选中,否者就会抛出异常。也可以使用   Qualifier这个属性来帮助解决多个候选者的问题。
		if (ele.hasAttribute(PRIMARY_ATTRIBUTE)) {
			bd.setPrimary(TRUE_VALUE.equals(ele.getAttribute(PRIMARY_ATTRIBUTE)));
		}

		//init-method  这个方法是Spring的生命周期中的一个方法。
		//在bean中设置的init-method方法的优先级比全局的优先级高。
		if (ele.hasAttribute(INIT_METHOD_ATTRIBUTE)) {
			String initMethodName = ele.getAttribute(INIT_METHOD_ATTRIBUTE);
			if (!"".equals(initMethodName)) {
				bd.setInitMethodName(initMethodName);
			}
		}
		else {
			if (this.defaults.getInitMethod() != null) {
				bd.setInitMethodName(this.defaults.getInitMethod());
				bd.setEnforceInitMethod(false);
			}
		}

		//bean对象被销毁是将会调用的方法,和init方法一样,<bean>中定义的优先级高于 全局定义的destory方法。
		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);
			}
		}

		//这两个属性是在Spring中使用工厂方来进行管理,其中一个是factory-bean,一个是factory-method。
		if (ele.hasAttribute(FACTORY_METHOD_ATTRIBUTE)) {
			bd.setFactoryMethodName(ele.getAttribute(FACTORY_METHOD_ATTRIBUTE));
		}
		if (ele.hasAttribute(FACTORY_BEAN_ATTRIBUTE)) {
			bd.setFactoryBeanName(ele.getAttribute(FACTORY_BEAN_ATTRIBUTE));
		}

		return bd;
	}

解析完attribute后,开始解析 meta属性了。

<bean id="zandan" class="com.test.bean.meta.MetaDataBean">
   		 <meta key="metaData" value="testMataData"/>
</bean>

看下是如何解析的:

public void parseMetaElements(Element ele, BeanMetadataAttributeAccessor attributeAccessor) {
		NodeList nl = ele.getChildNodes();
		for (int i = 0; i < nl.getLength(); i++) {
			Node node = nl.item(i);
			if (isCandidateElement(node) && nodeNameEquals(node, META_ELEMENT)) {//如果当前的Node是Spring自定义的,同时== meta数据
				Element metaElement = (Element) node;
				String key = metaElement.getAttribute(KEY_ATTRIBUTE);
				String value = metaElement.getAttribute(VALUE_ATTRIBUTE);
				BeanMetadataAttribute attribute = new BeanMetadataAttribute(key, value);//创建一个BeanMetaDataAttribute的属性。
				attribute.setSource(extractSource(metaElement));
				attributeAccessor.addMetadataAttribute(attribute);//将属性添加到AttributeAccessor中去。其中BeanMetadataAttributeAccessor是GenericBeanDefinition的属性。
			}
		}
	}

其中meta数据转变为一个BeanMetadataAttribute中去。

lookup属性的解析:

 <bean id="testLookUp" class="com.test.bean.lookUp.GetBeanTest" >
    	<lookup-method name="getUser" bean="student"/>
 </bean>
 <bean id="student" class="com.test.bean.lookUp.Teacher"/>

其中在GetBeanTest中定义了一个Abstract的方法,这个方法返回一个User类型的对象。
然后在Spring的配置文件中定义一个<lookup-method name="getUser"  bean = "student">其中 bean=“student”中定义的是User类型的子类。

首先看下解析过程,将<bean>定义的look-up相关内容转变为GenericBeanDefinition中的信息中的LookupOverride的内容。

public void parseLookupOverrideSubElements(Element beanEle, MethodOverrides overrides) {
		NodeList nl = beanEle.getChildNodes();
		for (int i = 0; i < nl.getLength(); i++) {
			Node node = nl.item(i);
			if (isCandidateElement(node) && nodeNameEquals(node, LOOKUP_METHOD_ELEMENT)) {//这个属性是LookUp方法。
				Element ele = (Element) node;
				String methodName = ele.getAttribute(NAME_ATTRIBUTE);
				String beanRef = ele.getAttribute(BEAN_ELEMENT);
				LookupOverride override = new LookupOverride(methodName, beanRef);//LookupOverride,这个方法是MethodOverride的子类。
				override.setSource(extractSource(ele));
				overrides.addOverride(override);//将当前的LookupOverride添加到当前系统中去。
			}
		}
	}

repleace-method的解析:

看下配置文件中的内容:

<bean id="testChangeMethod" class="com.test.bean.replace.TestChangeMethod">
    	<replaced-method name="changeMe" replacer="replacer"/>
</bean>
<bean id="replacer" class="com.test.bean.replace.TestMethodReplacer"/>

代码的实现:

public class TestChangeMethod {

    public void changeMe() {
        System.out.println("changeMe");
  	  }
	}
	
	public class TestMethodReplacer implements MethodReplacer {
    public Object reimplement(Object obj, Method method, Object[] args) throws Throwable {

        System.out.println("我替换了原有的方法");
        return null;
    }
}

replace-method主要是替换当前系统中的某一个方法.其中替换方法需要实现MethodReplacer的接口。
解析的过程中,最后是将replaceMethod的定义解析为 ReplaceOverride,然后添加到BeanDefinition中的Overrides中去。

public void parseReplacedMethodSubElements(Element beanEle, MethodOverrides overrides) {
		NodeList nl = beanEle.getChildNodes();
		for (int i = 0; i < nl.getLength(); i++) {
			Node node = nl.item(i);
			if (isCandidateElement(node) && nodeNameEquals(node, REPLACED_METHOD_ELEMENT)) {//判断当前对象是replce-method标签。
				Element replacedMethodEle = (Element) node;
				String name = replacedMethodEle.getAttribute(NAME_ATTRIBUTE);//获取被替换的方法。
				String callback = replacedMethodEle.getAttribute(REPLACER_ATTRIBUTE);//获取替换的bean
				ReplaceOverride replaceOverride = new ReplaceOverride(name, callback);//创建一个替换的Override的bean,这个bean被定义为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);
					match = (StringUtils.hasText(match) ? match : DomUtils.getTextValue(argTypeEle));
					if (StringUtils.hasText(match)) {
						replaceOverride.addTypeIdentifier(match);
					}
				}
				replaceOverride.setSource(extractSource(replacedMethodEle));
				overrides.addOverride(replaceOverride);//将overridede方法添加到GenericBeanDefinition中去。
			}
		}
	}

构造函数的解析:
通过构造函数来构造一个Bean。其中的过程如下:

<bean id="helloBean" class="com.test.bean.construct.HelloBean">
        <constructor-arg index="0">
            <value>张三</value>
        </constructor-arg>
        <constructor-arg index="1">
            <value>你好吗?</value>
        </constructor-arg>
</bean>

HelloBen的代码如下:

public class HelloBean {

    private String name;
    private String say;

    public HelloBean(String name, String say) {
        this.name = name;
        this.say = say;
    }

    public void sayHello() {
        System.out.println(name + " : " + say);
    }

}

看下解析Bean的Constructor中信息的过程:

public void parseConstructorArgElements(Element beanEle, BeanDefinition bd) {
		NodeList nl = beanEle.getChildNodes();
		for (int i = 0; i < nl.getLength(); i++) {
			Node node = nl.item(i);
			if (isCandidateElement(node) && nodeNameEquals(node, CONSTRUCTOR_ARG_ELEMENT)) {//获取到constructor-arg的属性。
				parseConstructorArgElement((Element) node, bd);//这个是关键
			}
		}
	}

具体的实现:

public void parseConstructorArgElement(Element ele, BeanDefinition bd) {
		String indexAttr = ele.getAttribute(INDEX_ATTRIBUTE);//根据Index来调用Constructor的Bean。
		String typeAttr = ele.getAttribute(TYPE_ATTRIBUTE);//根据Type来调用Constructor的Bean。
		String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);//根据Name来调用Constructor的Bean。
		if (StringUtils.hasLength(indexAttr)) {//其中index是最优先进行实例化的。
			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));
						Object value = parsePropertyValue(ele, bd, null);//解析当前element中的value值。
						ConstructorArgumentValues.ValueHolder valueHolder = new ConstructorArgumentValues.ValueHolder(value);//构造ConstructorArgumentValue属性。
						if (StringUtils.hasLength(typeAttr)) {//设置Type属性
							valueHolder.setType(typeAttr);
						}
						if (StringUtils.hasLength(nameAttr)) {//设置Name属性
							valueHolder.setName(nameAttr);
						}
						valueHolder.setSource(extractSource(ele));//设置source。
						if (bd.getConstructorArgumentValues().hasIndexedArgumentValue(index)) {//判断当前的Index是否设置过了,如果有过,就报错。
							error("Ambiguous constructor-arg entries for index " + index, ele);
						}
						else {
							bd.getConstructorArgumentValues().addIndexedArgumentValue(index, valueHolder);//将当前的ConstructorArgumentValue写到GenericBeanDefinition中去。其中写入的是IndexArgumentValue.在实例化的时候,index的优先级也会比当前的对象高。
						}
					}
					finally {
						this.parseState.pop();
					}
				}
			}
			catch (NumberFormatException ex) {
				error("Attribute 'index' of tag 'constructor-arg' must be an integer", ele);
			}
		}
		else {
			try {
				this.parseState.push(new ConstructorArgumentEntry());
				Object value = parsePropertyValue(ele, bd, null);//解析属性
				ConstructorArgumentValues.ValueHolder valueHolder = new ConstructorArgumentValues.ValueHolder(value);
				if (StringUtils.hasLength(typeAttr)) {
					valueHolder.setType(typeAttr);
				}
				if (StringUtils.hasLength(nameAttr)) {
					valueHolder.setName(nameAttr);
				}
				valueHolder.setSource(extractSource(ele));
				bd.getConstructorArgumentValues().addGenericArgumentValue(valueHolder);//将当前的type和和name相关的 GenericArgumentValue写入到当前BeanDefinition中去。
			}
			finally {
				this.parseState.pop();
			}
		}
	}

Spring中属性的设置主要有三种方式,其中是 在 attribute中  设置ref。一种是在attribute中设置value。还有一种是 在Property设置 子element 的属性。

//获取property element中的 value。可能是list属性。
//也有可能使用在constructor 属性中  propertyName可能为 null。
public Object parsePropertyValue(Element ele, BeanDefinition bd, String propertyName) {
		
		String elementName = (propertyName != null) ?
						"<property> element for property '" + propertyName + "'" :
						"<constructor-arg> element";//如果propertyName 为null的时候,elementName = constructor-arg。

		// Should only have one child element: ref, value, list, etc.//当前属性中应该只有一个子Element。
		NodeList nl = ele.getChildNodes();//所有的子Node属性。
		Element subElement = null;
		for (int i = 0; i < nl.getLength(); i++) {
			Node node = nl.item(i);
			if (node instanceof Element && !nodeNameEquals(node, DESCRIPTION_ELEMENT) &&
					!nodeNameEquals(node, META_ELEMENT)) {
				// Child element is what we're looking for.
				if (subElement != null) {
					error(elementName + " must not contain more than one sub-element", ele);
				}
				else {
					subElement = (Element) node;
				}
			}
		}

		boolean hasRefAttribute = ele.hasAttribute(REF_ATTRIBUTE);//当前的Property中是否有ref属性
		boolean hasValueAttribute = ele.hasAttribute(VALUE_ATTRIBUTE);//当前Property中是否有value属性。
		if ((hasRefAttribute && hasValueAttribute) ||
				((hasRefAttribute || hasValueAttribute) && subElement != null)) {// 如果当前Property中已经有了ref或者是value,这个时候就需要报错,因为已经重复了。
			error(elementName +
					" is only allowed to contain either 'ref' attribute OR 'value' attribute OR sub-element", ele);
		}

		if (hasRefAttribute) {//如果是在attribute中设置的ref。
			String refName = ele.getAttribute(REF_ATTRIBUTE);//获取到  ref对应的beanName。
			if (!StringUtils.hasText(refName)) {
				error(elementName + " contains empty 'ref' attribute", ele);
			}
			RuntimeBeanReference ref = new RuntimeBeanReference(refName);//构造RuntimeBeanReference。
			ref.setSource(extractSource(ele));
			return ref;//返回结果。
		}
		else if (hasValueAttribute) {
			TypedStringValue valueHolder = new TypedStringValue(ele.getAttribute(VALUE_ATTRIBUTE));
			valueHolder.setSource(extractSource(ele));
			return valueHolder;//返回TypeStringValue的值。
		}
		else if (subElement != null) {
			return parsePropertySubElement(subElement, bd);//返回解析SubElement的值。
		}
		else {
			// Neither child element nor "ref" or "value" attribute found.。如果 ref Attribute ,Value Attribute 以及  sub Element都为空的时候,这个时候就报错。
			error(elementName + " must specify a ref or value", ele);
			return null;
		}
	}

下面看下 public Object parsePropertySubElement(Element ele, BeanDefinition bd) 

public Object parsePropertySubElement(Element ele, BeanDefinition bd, String defaultValueType) {
		if (!isDefaultNamespace(ele)) {//如果当前的属性是用户自定义的Bean信息,调用解析用户自定义的属性。
			return parseNestedCustomElement(ele, bd);
		}
		else if (nodeNameEquals(ele, BEAN_ELEMENT)) {  //如果Element是一个bean的时候。
			BeanDefinitionHolder nestedBd = parseBeanDefinitionElement(ele, bd);//对当前的Bean进行解析。这个就是一个解析正常的Bean的过程。
			if (nestedBd != null) {
				nestedBd = decorateBeanDefinitionIfRequired(ele, nestedBd, bd);//对当前的Bean进行装饰
			}
			return nestedBd;//返回解析的Bean。
		}
		else if (nodeNameEquals(ele, REF_ELEMENT)) {  //如果Property中是ref类型的子Element
			//如果当前的Node是ref类型的。,主要包括  bean , ref 和  parent三种类型。对于这三种类型的实现。如果这三种 refName都为空的时候就报错误
			// A generic reference to any name of any bean.
			String refName = ele.getAttribute(BEAN_REF_ATTRIBUTE);//取出对应的Bean 的Name信息。
			boolean toParent = false;
			if (!StringUtils.hasLength(refName)) {//如果BeanName为空,这个时候就使用  local-ref
				// A reference to the id of another bean in the same XML file.
				refName = ele.getAttribute(LOCAL_REF_ATTRIBUTE);//将local-ref设置给  refName
				if (!StringUtils.hasLength(refName)) {
					// A reference to the id of another bean in a parent context.
					refName = ele.getAttribute(PARENT_REF_ATTRIBUTE); //如果localRef为null,这个时候需要将  parenet值设置为 refName.同时将
					toParent = true;
					if (!StringUtils.hasLength(refName)) {
						error("'bean', 'local' 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信息来构造一下RuntimeReference。
			ref.setSource(extractSource(ele));
			return ref;
		}
		else if (nodeNameEquals(ele, IDREF_ELEMENT)) {//idRef解析,idRef主要用来注入一个bean的Id,注入的其实还是 一个 String的信息。
			return parseIdRefElement(ele);
		}
		else if (nodeNameEquals(ele, VALUE_ELEMENT)) {
			return parseValueElement(ele, defaultValueType);
		}
		else if (nodeNameEquals(ele, NULL_ELEMENT)) {
			// It's a distinguished null value. Let's wrap it in a TypedStringValue
			// object in order to preserve the source location.
			TypedStringValue nullHolder = new TypedStringValue(null);
			nullHolder.setSource(extractSource(ele));
			return nullHolder;
		}
		else if (nodeNameEquals(ele, ARRAY_ELEMENT)) {
			return parseArrayElement(ele, bd);
		}
		else if (nodeNameEquals(ele, LIST_ELEMENT)) {
			return parseListElement(ele, bd);
		}
		else if (nodeNameEquals(ele, SET_ELEMENT)) {
			return parseSetElement(ele, bd);
		}
		else if (nodeNameEquals(ele, MAP_ELEMENT)) {
			return parseMapElement(ele, bd);
		}
		else if (nodeNameEquals(ele, PROPS_ELEMENT)) {
			return parsePropsElement(ele);
		}
		else {
			error("Unknown property sub-element: [" + ele.getNodeName() + "]", ele);
			return null;
		}
	}


看一下是如何解析 IdRef的Element的。其中返回的结果是一个RuntimeBeanNameReference的属性。
 

<! --   idref 主要通过  bean  和local两种方式来指定 -->
<idref bean="subClass"></idref>
<idref local="subClass"></idref>
public Object parseIdRefElement(Element ele) {
		// A generic reference to any name of any bean.
		String refName = ele.getAttribute(BEAN_REF_ATTRIBUTE);//获取到beanName。
		if (!StringUtils.hasLength(refName)) {//如果BeanName为空
			// A reference to the id of another bean in the same XML file.
			refName = ele.getAttribute(LOCAL_REF_ATTRIBUTE);//获取到localRef的信息
			if (!StringUtils.hasLength(refName)) {
				error("Either 'bean' or 'local' is required for <idref> element", ele);
				return null;
			}
		}
		if (!StringUtils.hasText(refName)) {   //如果这两种方式都没有对应的ref的信息,这个时候就报错。
			error("<idref> element contains empty target attribute", ele);
			return null;
		}
		RuntimeBeanNameReference ref = new RuntimeBeanNameReference(refName);
		ref.setSource(extractSource(ele));
		return ref;
	}

看一下  Value值是如何进行处理的:    返回的结果是一个  TypeStringValue

使用value值是这样设置的:

<property name="beanName" >
   <value type="java.lang.String">zhagnsan</value>
</property>

看下代码的实现:

/**
	 * Return a typed String value Object for the given value element.
	 */
	public Object parseValueElement(Element ele, String defaultTypeName) {
		// It's a literal value.
		String value = DomUtils.getTextValue(ele);//获取到其中的值
		String specifiedTypeName = ele.getAttribute(TYPE_ATTRIBUTE);//获取value对应的属性Type		String typeName = specifiedTypeName;
		if (!StringUtils.hasText(typeName)) {
			typeName = defaultTypeName;//设置默认的  typeName。
		}
		try {
			TypedStringValue typedValue = buildTypedStringValue(value, typeName);//构造  TypeStringValue的值,这个过程主要是将当前的对象添加到系统中。
			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;
		}
	}

看一下是如何设置 Array 的属性值的:这个array是一个数组。

<property name="reds">
            <array value-type="java.lang.Integer">
                <value>12</value>
                <value>23</value>
                <value>33</value>
            </array>
</property>

看一下解析的代码,解析后返回一个ManagedArray对象。

public Object parseArrayElement(Element arrayEle, BeanDefinition bd) {
		String elementType = arrayEle.getAttribute(VALUE_TYPE_ATTRIBUTE);//获取value-type的属性。
		NodeList nl = arrayEle.getChildNodes();//获取所有的属性
		ManagedArray target = new ManagedArray(elementType, nl.getLength());//创建一个MannagedArray
		target.setSource(extractSource(arrayEle));//设置source。
		target.setElementTypeName(elementType);//设置一下elementType的值
		target.setMergeEnabled(parseMergeAttribute(arrayEle));//设置一下当前对象中的 是否能够进行merge。
		parseCollectionElements(nl, target, bd, elementType);//其中对当中的一个nodeList进行解析,这个过程主要是一个循环的解析 sub Element。
		return target;
	}

List的解析和Array的解析相类似。

Set的解析也想类似,主要是是 返回的结果中的ManagedSet中继承的是一个HashSet,而List中依赖的是一个List。

看下Map的解析过程,返回的结果是一个ManageMap的实现。

<property name="map">
    <map key-type="java.lang.String" value-type="java.lang.String">
         <entry key="lisi">
              <value>lisi</value>
         </entry>
         <entry key="wangwu">
               <value>wangwu</value>
         </entry>
     </map>
</property>
/**
	 * Parse a map element.
	 */
	public Map<Object, Object> parseMapElement(Element mapEle, BeanDefinition bd) {
		String defaultKeyType = mapEle.getAttribute(KEY_TYPE_ATTRIBUTE);// 关键的key的类型值
		String defaultValueType = mapEle.getAttribute(VALUE_TYPE_ATTRIBUTE);// value 的类型值

		List<Element> entryEles = DomUtils.getChildElementsByTagName(mapEle, ENTRY_ELEMENT);//获取到所有的Entry中的值
		ManagedMap<Object, Object> map = new ManagedMap<Object, Object>(entryEles.size());//创建一个MangedMap的值
		map.setSource(extractSource(mapEle));//设置 source
		map.setKeyTypeName(defaultKeyType);//设置  keyType的值
		map.setValueTypeName(defaultValueType);//设置value的Type值
		map.setMergeEnabled(parseMergeAttribute(mapEle));//解析元素的合并元素

		for (Element entryEle : entryEles) {//对当前的EntryElement进行分别的解析。
			// Should only have one value child element: ref, value, list, etc.
			// Optionally, there might be a key child element.
			NodeList entrySubNodes = entryEle.getChildNodes();//获取到NodeList。其中每一个Node代表的是一个entry。
			Element keyEle = null;  //key值
			Element valueEle = null;//value值
			for (int j = 0; j < entrySubNodes.getLength(); j++) {
				Node node = entrySubNodes.item(j);
				if (node instanceof Element) {
					Element candidateEle = (Element) node;
					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.
			//提取Key值:key值有三种情况,第一种是  TypedStringValue。第二种是 RuntimeBeanReference。第三种可能是一个subElement对应的对象。
			Object key = null;
			boolean hasKeyAttribute = entryEle.hasAttribute(KEY_ATTRIBUTE);//查看下当前的实现是否包含了 key值
			boolean hasKeyRefAttribute = entryEle.hasAttribute(KEY_REF_ATTRIBUTE);//看下是否包含了keyref
			if ((hasKeyAttribute && hasKeyRefAttribute) ||
					((hasKeyAttribute || hasKeyRefAttribute)) && keyEle != null) {//key的值不能为同时为空
				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值不为空,这个时候,key为一个 TypeStringValue的值。
				key = buildTypedStringValueForMap(entryEle.getAttribute(KEY_ATTRIBUTE), defaultKeyType, entryEle);
			}
			else if (hasKeyRefAttribute) {//如果keyRefAttribute不为null,这个时候需要完成的工作是创建一个RuntimeBeanReference的对象。
				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);//获取到key的value值。
			}
			else {
				error("<entry> element must specify a key", entryEle);
			}

			// 从Value提取对应的值。其中关键的是
			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);//将结果添加到一个 ManagedMap<Object,Object>当中去。
		}

		return map;
	}

Map解析起来比较的复杂,主要是map中的key和value都可能是 value,ref,其他的subElement。这三种定义返回的结果都不一样,分别返回TypeStringValue,RuntimeBeanRegerence以及调用parseSubElement返回的结果。

下面看下 解析Qualifier 当中的属性元素:
Qualifier:主要解决的问题是按照类型进行注入的时候,当同一个类型找到了多个bean的时候,这个时候会发生歧义,会报错。这个时候使用Qualifer来指定其中一个值。解析结果是一个AutowireCandidateQualifier对象:

 <bean id="helloBean" class="com.test.bean.construct.HelloBean">
    <qualifier type="" value=""/>
</bean>
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);//解析 Qualifier的实现。
			}
		}
	}
public void parseQualifierElement(Element ele, AbstractBeanDefinition bd) {
		String typeName = ele.getAttribute(TYPE_ATTRIBUTE); //注入的Type类型的名称、
		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);//创建一个AutowireCandidateQualifier对象其中有了所有的待注入的内容对象的类型。
			qualifier.setSource(extractSource(ele));//设置source的值
			String value = ele.getAttribute(VALUE_ATTRIBUTE);//找到对应的value值
			if (StringUtils.hasLength(value)) {//如果确实设置了value值
				qualifier.setAttribute(AutowireCandidateQualifier.VALUE_KEY, value);
			}
			NodeList nl = ele.getChildNodes();
			for (int i = 0; i < nl.getLength(); i++) {//在设置底层的对象。
				Node node = nl.item(i);
				if (isCandidateElement(node) && nodeNameEquals(node, QUALIFIER_ATTRIBUTE_ELEMENT)) {
					Element attributeEle = (Element) node;
					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();
		}
	}

以上为解析<bean>为一个GenericBeanDefinition的关键步骤。

4.6.1.4如果当前的beanName为空,就为这个对象生成一个默认的beanName。

生成默认的BeanName的算法 看下:
首先使用生成的Bean的Class的name。然后如果为空,就使用 parenetName+"$child"。接着还为空,就使用 factoryBeanName+"$created".最后还是为空,这个时候就报错。
然后需要处理一下重复的内容,如果是innerClass,这个时候,需要完成的功能是 id = id+"#"+hashCode. 如果这个对象当中已经有了额外的对象。这个时候可以使用  id= id+counter

看下代码:

public static String generateBeanName(
			BeanDefinition definition, BeanDefinitionRegistry registry, boolean isInnerBean)
			throws BeanDefinitionStoreException {

		String generatedBeanName = definition.getBeanClassName();//获取到当期那bean对应的ClassName
		if (generatedBeanName == null) {
			if (definition.getParentName() != null) {
				generatedBeanName = definition.getParentName() + "$child";// parenetName+"$child".
			}
			else if (definition.getFactoryBeanName() != null) {
				generatedBeanName = definition.getFactoryBeanName() + "$created";//factroyBeanName+"$created".
			}
		}
		if (!StringUtils.hasText(generatedBeanName)) {//如果这三个还是为空,那么久报错
			throw new BeanDefinitionStoreException("Unnamed bean definition specifies neither " +
					"'class' nor 'parent' nor 'factory-bean' - can't generate bean name");
		}

		String id = generatedBeanName;
		if (isInnerBean) {//如果当前的class是一个innerBean,这个时候,需要完成的是 generateBeanName +"#"+当前Bean对应的Hashcode的唯一值。
			// Inner bean: generate identity hashcode suffix.
			id = generatedBeanName + GENERATED_BEAN_NAME_SEPARATOR + ObjectUtils.getIdentityHexString(definition);
		}
		else {
			// Top-level bean: use plain class name.
			// Increase counter until the id is unique.
			int counter = -1;
			while (counter == -1 || registry.containsBeanDefinition(id)) {//如果当前的beanRegistry中如果包括了对应BeanName了。这个时候需要不断的对当前counter进行自增。
				counter++;
				id = generatedBeanName + GENERATED_BEAN_NAME_SEPARATOR + counter;
			}
		}
		return id;
	}

4.6.1.5 构造BeanDefinitionHolder

将GenericBeanDefinition和beanName和aliasName一起构造一个BeanDefinitionHolder对象。

 

 

4.6.2 扩展当前BeanDefinitionHolder
BeanDefinitionHolder decorateBeanDefinitionIfRequired(
            Element ele, BeanDefinitionHolder definitionHolder, BeanDefinition containingBd)
            这个当中完成的功能,主要是用户在Element中自定义了attribute和子childNode:

public BeanDefinitionHolder decorateBeanDefinitionIfRequired(
			Element ele, BeanDefinitionHolder definitionHolder, BeanDefinition containingBd) {

		BeanDefinitionHolder finalDefinition = definitionHolder;//这个是解析完成的BeanDefinitionHolder。

		// Decorate based on custom attributes first.这个主要是用户在Element中定义的 attribute的信息。
		NamedNodeMap attributes = ele.getAttributes();//获取到所有的attribute。
		for (int i = 0; i < attributes.getLength(); i++) {
			Node node = attributes.item(i);
			finalDefinition = decorateIfRequired(node, finalDefinition, containingBd);//如果其中有用户自定义的一些命名空间的内容,这个时候需要额外的调用对应NameSpaceHandlerResolver对象来对当前的对象进行额外的操作。
		}

		// Decorate based on custom nested elements.这个表示在当前Element中定义的  childNode信息。这些childNode是用户自定义相关的内容。
		NodeList children = ele.getChildNodes();
		for (int i = 0; i < children.getLength(); i++) {
			Node node = children.item(i);
			if (node.getNodeType() == Node.ELEMENT_NODE) {
				finalDefinition = decorateIfRequired(node, finalDefinition, containingBd);
			}
		}
		return finalDefinition;
	}

4.6.3 注册BeanDefinition到BeanDefintionRegistry

将构造好的一个Bean写到BeanDefinitionRegistry中去:
调用了一个util方法:BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
看一下这个方法是如何实现的:

public static void registerBeanDefinition(
			BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
			throws BeanDefinitionStoreException {

		// Register bean definition under primary name.
		String beanName = definitionHolder.getBeanName();//获取到对应的beanName。
		registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition()); //这个方法是将当前生成的GenericBeanDefinition。

		// Register aliases for bean name, if any.
		String[] aliases = definitionHolder.getAliases();
		if (aliases != null) {
			for (String alias : aliases) {
				registry.registerAlias(beanName, alias);//将别名注册到BeanDefinitionRegistry中去。
			}
		}
	}

看下在DefaultListableBeanFactory是如何注册的这个看下:

public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)//beanName  和  beanDefinition
			throws BeanDefinitionStoreException {

		Assert.hasText(beanName, "Bean name must not be empty");
		Assert.notNull(beanDefinition, "BeanDefinition must not be null");

		if (beanDefinition instanceof AbstractBeanDefinition) {//如果这个对象是AbstractBeanDefinition的实例。需要进行验证一下
			try {
				((AbstractBeanDefinition) beanDefinition).validate();//如果bean中有BeanClass对象,同时,Bean中有 OverrideMethod的时候,这个时候需要测试一下。
			}
			catch (BeanDefinitionValidationException ex) {
				throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
						"Validation of bean definition failed", ex);
			}
		}

		BeanDefinition oldBeanDefinition;

		oldBeanDefinition = this.beanDefinitionMap.get(beanName);//获取到当前beanName在当前 Registry中已经存在的。
		if (oldBeanDefinition != null) {//如果 这个是替换
			if (!isAllowBeanDefinitionOverriding()) { //如果不允许替换,直接抛异常。
				throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
						"Cannot register bean definition [" + beanDefinition + "] for bean '" + beanName +
						"': There is already [" + oldBeanDefinition + "] bound.");
			}
			else if (oldBeanDefinition.getRole() < beanDefinition.getRole()) {//判断一下不同的bean的role,这个时候需要打印一条提示日志。
				// e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
				if (this.logger.isWarnEnabled()) {
					this.logger.warn("Overriding user-defined bean definition for bean '" + beanName +
							"' with a framework-generated bean definition: replacing [" +
							oldBeanDefinition + "] with [" + beanDefinition + "]");
				}
			}
			else if (!beanDefinition.equals(oldBeanDefinition)) {//如果当前的bean和旧bean不相同的时候,这个时候就打印日志。
				if (this.logger.isInfoEnabled()) {
					this.logger.info("Overriding bean definition for bean '" + beanName +
							"' with a different definition: replacing [" + oldBeanDefinition +
							"] with [" + beanDefinition + "]");
				}
			}
			else {
				if (this.logger.isDebugEnabled()) {
					this.logger.debug("Overriding bean definition for bean '" + beanName +
							"' with an equivalent definition: replacing [" + oldBeanDefinition +
							"] with [" + beanDefinition + "]");
				}
			}
			this.beanDefinitionMap.put(beanName, beanDefinition);//将当前的bean添加到beanMap中去。		}
		else {
			if (hasBeanCreationStarted()) {//创建BeanMap是否开始了。这个时候判断一下当前的 alreadyCreated是否已经开始创建bean了
				// Cannot modify startup-time collection elements anymore (for stable iteration)
				synchronized (this.beanDefinitionMap) {//对当前对象进行加锁
					this.beanDefinitionMap.put(beanName, beanDefinition);//将beanDefinition添加到Map中去。
					List<String> updatedDefinitions = new ArrayList<String>(this.beanDefinitionNames.size() + 1);//修改过的beanDefinitions的数量。
					updatedDefinitions.addAll(this.beanDefinitionNames);//将旧的beanDedinitions添加到updateDefinitions中去、
					updatedDefinitions.add(beanName);//然后将当前的beanName添加到 updateBeanDefinitions。
					this.beanDefinitionNames = updatedDefinitions;//这个时候使用 copyOfWrite来实现BeanDefinition的设置。
					if (this.manualSingletonNames.contains(beanName)) {
						Set<String> updatedSingletons = new LinkedHashSet<String>(this.manualSingletonNames);//如果有手动添加的单例Bean,这个时候需要将当前的bean删除掉。
						updatedSingletons.remove(beanName);
						this.manualSingletonNames = updatedSingletons;
					}
				}
			}
			else {
				// 如果还没有开始创建,同时也不是覆盖
				this.beanDefinitionMap.put(beanName, beanDefinition);//将当前的bean添加到bean中去
				this.beanDefinitionNames.add(beanName);//beanDefinitionNames添加beanName
				this.manualSingletonNames.remove(beanName);//从手动单例Name中删除 beanName的信息。
			}
			this.frozenBeanDefinitionNames = null;
		}

		//如果就的BeanDefinition不为空,或者是singletonBean的队列中包含了当前的bean。这个时候需要对当前的bean进行重新加载。
		if (oldBeanDefinition != null || containsSingleton(beanName)) {
			resetBeanDefinition(beanName);
		}
	}

看下是如何复位BeanDefinition对象的:

protected void resetBeanDefinition(String beanName) {
		// Remove the merged bean definition for the given bean, if already created.
		clearMergedBeanDefinition(beanName);//首先将当前的beanName的bean对象从 mergedBeanDefinitionMap中移除

		// Remove corresponding bean from singleton cache, if any. Shouldn't usually
		// be necessary, rather just meant for overriding a context's default beans
		// (e.g. the default StaticMessageSource in a StaticApplicationContext).
		destroySingleton(beanName);//将当前的单例给删除掉

		// Reset all bean definitions that have the given bean as parent (recursively).
		//将所有的bean继承于当前的bean,都需要进行一下复位。
		for (String bdName : this.beanDefinitionNames) {
			if (!beanName.equals(bdName)) {
				BeanDefinition bd = this.beanDefinitionMap.get(bdName);
				if (beanName.equals(bd.getParentName())) {
					resetBeanDefinition(bdName);
				}
			}
		}
	}

 

© 著作权归作者所有

粉丝 0
博文 7
码字总数 19795
作品 0
私信 提问
深入理解Spring源码(一)-IOC容器的定位,载入,注册

前言:Spring源码继承,嵌套层次非常多,读起来非常容易晕,小伙伴们在看文章的时候一定要跟着文章的思路自己去源码里点一点,看一看,并且多看几次。就会越来越清晰。下面开始正题 1.Spring...

Meet相识_bfa5
2018/05/01
0
0
Spring源码解析系列之IOC容器(一)

前言 实际上我所有的博客都是原来对原来印象笔记里笔记内容的加工,关于Spring源码自己已经解析了很多遍,但是时间长总是忘记,写一篇博客权当加强记忆,也算再次学习下大师们的设计思想,思...

后厂村老司机
2018/06/02
0
0
【死磕 Spring】—– IOC 之 IOC 初始化总结

原文出自:http://cmsblogs.com 前面 13 篇博文从源码层次分析了 IOC 整个初始化过程,这篇就这些内容做一个总结将其连贯起来。 在前文提过,IOC 容器的初始化过程分为三步骤:Resource 定位...

chenssy
2018/10/09
0
0
Spring IOC 实现原理

Spring IOC 实现原理 IOC: Inversion of Control ,即 "控制反转" , 不是什么技术,而是一种思想。原先需要自行实例化的对象, 交给IOC容器去实现。那么控制反转,谁被控制? 谁被反转 ? 在...

起个名忒难
2018/05/17
0
0
通过循环依赖问题彻底理解SpringIOC的精华

前言 你可能会有如下问题: 1、想看Spring源码,但是不知道应当如何入手去看,对整个Bean的流程没有概念,碰到相关问题也没有头绪如何下手 2、看过几遍源码,没办法彻底理解,没什么感觉,没...

Java填坑之路
2018/11/19
0
0

没有更多内容

加载失败,请刷新页面

加载更多

mac环境编译facets

facets是Google开源的数据可视化工具。首页:https://pair-code.github.io/facets/。 体验:https://colab.research.google.com/github/PAIR-code/facets/blob/master/colab_facets.ipynb#sc......

孟飞阳
24分钟前
2
0
代码保护软件VMProtect用户手册控制面板“项目”部分都有哪些功能?

VMProtect是一种很可靠的工具,可以保护应用程序代码免受分析和破解,但只有在应用程序内保护机制正确构建且没有可能破坏整个保护的严重错误的情况下,才能实现最好的效果。 【下载VMProtect...

mnrssj
28分钟前
1
0
房子在买入两年后出手要涨幅多少才能保证不亏(粗略计算)

7日年化收益率12% 属于高利贷么 首先,将年化转换为日化的1w的日收益 0.12*10000/365 = 3.19 我们看一下余额宝7日年化2.485%1w的日收益 0.02485*10000/365 = 0.68 借贷双方约定年利率 年利率...

小小明童鞋
29分钟前
98
1
rapidjson之原位解析(Insitu parse)

什么是原位解析 一种空间复杂度为O(1)的解析方式。正常解析方式需要将JSON字符串复制到其他缓冲区进行解析,这样将会消耗时间和空间复杂度。而原位解析则在JSON字符串所在的原空间进行操作,...

SibylY
31分钟前
1
0
使用gradle打包

安装包到https://gradle.org/下载 然后 将文件解压到自定文件夹,配置环境变量 新建环境变量 GRADLE_HOME,即 D:\usr\local\gradle-2.4; 修改环境变量 Path,即追加 %GRADLE_HOME%\BIN; 打包...

青峰Jun19er
34分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部