接着上篇文章我們繼續來做構造器配置與屬性配置的解析過程分析;
我們先來看看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註冊的方法調用過程;
`