接着上篇文章我们继续来做构造器配置与属性配置的解析过程分析;
我们先来看看BeanDefinitionParserDelegate是怎么来解析构造属性配置的;
public void parseConstructorArgElements(Element beanEle, BeanDefinition bd) {
//拿到子元素集合
NodeList nl = beanEle.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
//如果子元素是constructor-arg的话
if (isCandidateElement(node) && nodeNameEquals(node, CONSTRUCTOR_ARG_ELEMENT)) {
parseConstructorArgElement((Element) node, bd);
}
}
}
public void parseConstructorArgElement(Element ele, BeanDefinition bd) {
String indexAttr = ele.getAttribute(INDEX_ATTRIBUTE);//拿到配置index的值
String typeAttr = ele.getAttribute(TYPE_ATTRIBUTE);//拿到配置type的值
String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);//拿到配置的name的值
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));
//拿到该元素的值,对于我们的配置
//<constructor-arg index="0" name="color" value="黄色"/>
//在这里,我们会得到一个TypedStringValue,它的属性value值为"黄色"
Object value = parsePropertyValue(ele, bd, null);
ConstructorArgumentValues.ValueHolder valueHolder = new ConstructorArgumentValues.ValueHolder(value);
if (StringUtils.hasLength(typeAttr)) {
valueHolder.setType(typeAttr);
}
if (StringUtils.hasLength(nameAttr)) {
valueHolder.setName(nameAttr);
}
valueHolder.setSource(extractSource(ele));
if (bd.getConstructorArgumentValues().hasIndexedArgumentValue(index)) {
error("Ambiguous constructor-arg entries for index " + index, ele);
}
else {
//将对构造器的xml配置解析后而转换成的valueHolder对象存入bd中,为后面的bean的实例化操作提供支持
//在内部,bd将采用constructorArgumentValues属性的Map<Integer, ValueHolder> indexedArgumentValues 属性来存放valueHolder
bd.getConstructorArgumentValues().addIndexedArgumentValue(index, valueHolder);
}
}
finally {
this.parseState.pop();
}
}
}
catch (NumberFormatException ex) {
error("Attribute 'index' of tag 'constructor-arg' must be an integer", ele);
}
}
//解析某个元素并返回配置的值
public Object parsePropertyValue(Element ele, BeanDefinition bd, String propertyName) {
String elementName = (propertyName != null) ?
"<property> element for property '" + propertyName + "'" :
"<constructor-arg> element";
NodeList nl = ele.getChildNodes();
//拿到property下的子元素,也就是list,set,map...等配置
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)) {
if (subElement != null) {
error(elementName + " must not contain more than one sub-element", ele);
}
else {
subElement = (Element) node;
}
}
}
//是否配置了ref
boolean hasRefAttribute = ele.hasAttribute(REF_ATTRIBUTE);
//是否配置了value
boolean hasValueAttribute = ele.hasAttribute(VALUE_ATTRIBUTE);
//如果两个都配置了,就抛出异常
if ((hasRefAttribute && hasValueAttribute) ||
((hasRefAttribute || hasValueAttribute) && subElement != null)) {
error(elementName +
" is only allowed to contain either 'ref' attribute OR 'value' attribute OR sub-element", ele);
}
//如果配置了ref,则生成一个RuntimeBeanReference对象,它代表着对另一个bean的依赖
if (hasRefAttribute) {
String refName = ele.getAttribute(REF_ATTRIBUTE);
if (!StringUtils.hasText(refName)) {
error(elementName + " contains empty 'ref' attribute", ele);
}
RuntimeBeanReference ref = new RuntimeBeanReference(refName);
ref.setSource(extractSource(ele));
return ref;
}
//如果配置了value,则生成一个TypedStringValue,它代表着普通的对象属性值
else if (hasValueAttribute) {
TypedStringValue valueHolder = new TypedStringValue(ele.getAttribute(VALUE_ATTRIBUTE));
valueHolder.setSource(extractSource(ele));
return valueHolder;
}
else if (subElement != null) {
//如果有子元素,则继续对propertiy的子元素进行解析
return parsePropertySubElement(subElement, bd);
}
else {
error(elementName + " must specify a ref or value", ele);
return null;
}
}
//对properts下的子元素配置进行解析,在解析pants时不会进入这个方法,而person这个bean因为我们配置了girls这个list属性,所以会进入
public Object parsePropertySubElement(Element ele, BeanDefinition bd, 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;
}
//如果是ref...
else if (nodeNameEquals(ele, REF_ELEMENT)) {
String refName = ele.getAttribute(BEAN_REF_ATTRIBUTE);
boolean toParent = false;
if (!StringUtils.hasLength(refName)) {
refName = ele.getAttribute(LOCAL_REF_ATTRIBUTE);
if (!StringUtils.hasLength(refName)) {
refName = ele.getAttribute(PARENT_REF_ATTRIBUTE);
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.setSource(extractSource(ele));
return ref;
}
else if (nodeNameEquals(ele, IDREF_ELEMENT)) {
return parseIdRefElement(ele);
}
else if (nodeNameEquals(ele, VALUE_ELEMENT)) {
return parseValueElement(ele, defaultValueType);
}
else if (nodeNameEquals(ele, NULL_ELEMENT)) {
TypedStringValue nullHolder = new TypedStringValue(null);
nullHolder.setSource(extractSource(ele));
return nullHolder;
}
else if (nodeNameEquals(ele, ARRAY_ELEMENT)) {
return parseArrayElement(ele, bd);
}
//如果是list
else if (nodeNameEquals(ele, LIST_ELEMENT)) {
//我们配置的是list,进入这个方法去看看
return parseListElement(ele, bd);
}
//如果是set
else if (nodeNameEquals(ele, SET_ELEMENT)) {
return parseSetElement(ele, bd);
}
//如果是map
else if (nodeNameEquals(ele, MAP_ELEMENT)) {
return parseMapElement(ele, bd);
}
else if (nodeNameEquals(ele, PROPS_ELEMENT)) {
return parsePropsElement(ele);
}
else {
error("Unknown property sub-element: [" + ele.getNodeName() + "]", ele);
return null;
}
}
//解析list配置
public List<Object> parseListElement(Element collectionEle, BeanDefinition bd) {
String defaultElementType = collectionEle.getAttribute(VALUE_TYPE_ATTRIBUTE);
NodeList nl = collectionEle.getChildNodes();
//使用ManagedList集合来存放解析后的记录,而每一条记录被解析后实际上也是生成上面的TypedStringValue对象!
ManagedList<Object> target = new ManagedList<Object>(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, 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));
}
}
}
OK,现在,我们配置的两个bean已经解析完成且根据配置元素构建好了BeanDefinition,这个过程看似代码很多而实际上也是很简单的,
BeanDefinitionParserDelegate先是在parseBeanDefinitionElement(Element ele, String beanName, BeanDefinition containingBean) 方法中创建一个GenericBeanDefinition,创建好后调用多个方法来填充GenericBeanDefinition的属性值,比如调用parseConstructorArgElements()来解析构造配置并将解析后的值转换为constructorArgumentValues属性的indexedArgumentValues属性中保存起来;把对property的解析结果则会放入propertyValues属性的List<PropertyValue> propertyValueList之中,代码如下:
public void parsePropertyElement(Element ele, BeanDefinition bd) {
String propertyName = ele.getAttribute(NAME_ATTRIBUTE);
if (!StringUtils.hasLength(propertyName)) {
error("Tag 'property' must have a 'name' attribute", ele);
return;
}
this.parseState.push(new PropertyEntry(propertyName));
try {
if (bd.getPropertyValues().contains(propertyName)) {
error("Multiple 'property' definitions for property '" + propertyName + "'", ele);
return;
}
Object val = parsePropertyValue(ele, bd, propertyName);
//看这里
PropertyValue pv = new PropertyValue(propertyName, val);
parseMetaElements(ele, pv);
pv.setSource(extractSource(ele));
bd.getPropertyValues().addPropertyValue(pv);
}
finally {
this.parseState.pop();
}
}
BeanDefinition配置好后,BeanDefinitionParserDelegate类将创建一个BeanDefinitionHolder类且返回给DefaultBeanDefinitionDocumentReader,BeanDefinitionHolder这个类就是对BeanDefinition的一层包装而已;
回到我们的DefaultBeanDefinitionDocumentReader的processBeanDefinition方法之中,我们来看看拿到BeanDefinitionHolder后接下来要做什么;
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
//调用工具类注册这个bean!getRegistry()将返回当前beanFactory,也就是DefaultListableBeanFactory
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
}
catch (BeanDefinitionStoreException ex) {
getReaderContext().error("Failed to register bean definition with name '" +
bdHolder.getBeanName() + "'", ele, ex);
}
// Send registration event.
getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
}
}
进入到DefaultListableBeanFactory类的registerBeanDefinition()中去看看;
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
Assert.hasText(beanName, "Bean name must not be empty");
Assert.notNull(beanDefinition, "BeanDefinition must not be null");
if (beanDefinition instanceof AbstractBeanDefinition) {
try {
((AbstractBeanDefinition) beanDefinition).validate();
}
catch (BeanDefinitionValidationException ex) {
throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
"Validation of bean definition failed", ex);
}
}
BeanDefinition oldBeanDefinition;
//如果已经存在这个名称代表的bean,则抛出异常
oldBeanDefinition = this.beanDefinitionMap.get(beanName);
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()) {
// 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 (this.logger.isInfoEnabled()) {
this.logger.info("Overriding bean definition for bean '" + beanName +
"': replacing [" + oldBeanDefinition + "] with [" + beanDefinition + "]");
}
}
}
else {
this.beanDefinitionNames.add(beanName);
this.manualSingletonNames.remove(beanName);
this.frozenBeanDefinitionNames = null;
}
//我们看到,spring在beanFactory内部就是用一个map来管理beanDefinition的
this.beanDefinitionMap.put(beanName, beanDefinition);
if (oldBeanDefinition != null || containsSingleton(beanName)) {
resetBeanDefinition(beanName);
}
}
现在,我们的BeanDefinition已经注册到BeanFactory容器中去了,它被保存在了一个map集合中,整个IOC容器的资源定位,解析,bean注册过程到这里就结束了,只是,我们的Bean到现在都还没有看到影子,说来说去一直围绕着BeanDefition类在打转,那我们的Bean是在什么时候才会被实例化呢? 答案是第一次使用这个Bean的时候!而spring去实例化Bean时,需要去根据名称或者类型去上面的map集合中拿到BeanDefinition,然后再取出我们上面设置好的各种属性值,再通过反射生成对应的Bean实例!在下篇文章中,我们就来分析实例化Bean的过程;
最后,结合上一篇文章,我们来画一个时序图帮助我们理解下资源解析和beanDefinition注册的方法调用过程;
`