相关文章
Spring IOC系列学习笔记一:前置刷新
Spring IOC系列学习笔记二:obtainFreshBeanFactory方法
Spring IOC系列学习笔记三:parseDefaultElement详解
Spring IOC系列学习笔记四:parseCustomElement解析
Spring IOC系列学习笔记五:context:component-scan 节点解析
Spring IOC系列学习笔记六:invokeBeanFactoryPostProcessors解析
Spring IOC系列学习笔记七:registerBeanPostProcessors
Spring IOC系列学习笔记八:finishBeanFactoryInitialization
Spring IOC系列学习笔记九:getBean方法
Spring IOC系列学习笔记十:createBean方法(上)
Spring IOC系列学习笔记十一:createBean方法(下)
Spring IOC系列学习笔记十二:@Autowire注解
文章目录
- 相关文章
- 前言
- 代码块一:parseDefaultElement
- 代码块二:processBeanDefinition
- 代码块三:parseBeanDefinitionElement
- 代码块四:parseBeanDefinitionElement
- 代码块五:parseBeanDefinitionAttributes
- 代码块六:parseConstructorArgElements
- 代码块七:parseConstructorArgElement
- 代码块八:parsePropertyValue
- 代码块九:parsePropertySubElement
- 代码块十:parseValueElement
- 代码块十一:buildTypedStringValue
- 代码块十二:parseListElement
- 代码块十三:parsePropertyElements
- 代码块十四:registerBeanDefinition
- 代码块十五:registerBeanDefinition
- 代码块十六:registerAlias
- 总结
前言
继续Spring系列学习笔记二:obtainFreshBeanFactory方法的讲解,下面我们进入对默认的命名空间的处理,进入parseDefaultElement方法中。
代码块一:parseDefaultElement
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
1、解析import节点
if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
importBeanDefinitionResource(ele);
}
2、解析alias节点
else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
processAliasRegistration(ele);
}
3、解析bean节点
else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
processBeanDefinition(ele, delegate);
}
4、解析beans节点
else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
doRegisterBeanDefinitions(ele);
}
}
可以看到默认的命名空间一共有四个标签,分别是bean、import、beans、alias标签。我们只介绍bean标签这个是比较复杂的其他的就比较好理解了。
3、解析bean节点 见代码块二
代码块二:processBeanDefinition
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
1、解析bean节点,bdHolder包含了该节点的BeanDefinition,name,和alias。
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {
2、注册自定义的标签, 比如这个就是自定义标签
//<bean id="animal" class="test.constructor.Animal">
//<myTag:my value="p1"/>
// </bean>
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
// Register the final decorated instance.
3、注册bdHolder
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
}
catch (BeanDefinitionStoreException ex) {
getReaderContext().error("Failed to register bean definition with name '" +
bdHolder.getBeanName() + "'", ele, ex);
}
// Send registration event.
4、发出响应事件表示该bean已经注册完成
getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
}
}
1、解析bean节点见代码块三
3、注册bean见代码块代码块十四
代码块三:parseBeanDefinitionElement
@Nullable
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) {
1、1获取id属性
String id = ele.getAttribute(ID_ATTRIBUTE);
1.2、获取name属性
String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
List<String> aliases = new ArrayList<>();
if (StringUtils.hasLength(nameAttr)) {
1.3、分割nameArr字符,可能取了几个别名
String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
aliases.addAll(Arrays.asList(nameArr));
}
String beanName = id;
1.4、如果没指定id,则指定name的第一个为别名
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) {
2、检查当前bean的名字在同一个<beans>下是否已经存在
checkNameUniqueness(beanName, aliases, ele);
}
3、解析bean节点
AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
if (beanDefinition != null) {
4、如果既没有指定name也没有指定id则进入
if (!StringUtils.hasText(beanName)) {
try {
if (containingBean != null) {
4.1如果bean定义已经存在,则这种规则生成一个bean的名字
beanName = BeanDefinitionReaderUtils.generateBeanName(
beanDefinition, this.readerContext.getRegistry(), true);
}
else {
4.2如果bean定义不存在,则由spring提供的规则生成
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)) {
4.3将该类名注册为别名
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);
5.封装成BeanDefinitionHolder
return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
}
return null;
}
3、解析bean节点见代码块四
代码块四:parseBeanDefinitionElement
@Nullable
public AbstractBeanDefinition parseBeanDefinitionElement(
Element ele, String beanName, @Nullable BeanDefinition containingBean) {
1、一个标志代表解析已经开始了 最后会移除
this.parseState.push(new BeanEntry(beanName));
String className = null;
2、获取calss属性
if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
}
String parent = null;
2.1获取parent属性
if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
parent = ele.getAttribute(PARENT_ATTRIBUTE);
}
try {
3、根据class和parent创建一个AbstractBeanDefinition,
AbstractBeanDefinition bd = createBeanDefinition(className, parent);
4、解析bean标签的属性
parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));
5、解析<meta>
parseMetaElements(ele, bd);
6、解析<lookup-method>
parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
7、解析<replaced-method>
parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
8、解析 <constructor-arg>
parseConstructorArgElements(ele, bd);
9、解析<property>
parsePropertyElements(ele, bd);
10、解析<qualifier>
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;
}
3、直接new GenericBeanDefinition比较简单,然后根据className和classLoader判断是否通过反射出一个实例并添加到GenericBeanDefinition中。
4、解析bean标签的属性见代码块五
8、解析 见代码块六
9、解析见代码块十三
代码块五:parseBeanDefinitionAttributes
public AbstractBeanDefinition parseBeanDefinitionAttributes(Element ele, String beanName,
@Nullable BeanDefinition containingBean, AbstractBeanDefinition bd) {
1.1、新版本已经不用singleton属性 如果有则抛出异常
if (ele.hasAttribute(SINGLETON_ATTRIBUTE)) {
error("Old 1.x 'singleton' attribute in use - upgrade to 'scope' declaration", ele);
}
1.2、 设置scope属性
else if (ele.hasAttribute(SCOPE_ATTRIBUTE)) {
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());
}
2、设置abstract属性
if (ele.hasAttribute(ABSTRACT_ATTRIBUTE)) {
bd.setAbstract(TRUE_VALUE.equals(ele.getAttribute(ABSTRACT_ATTRIBUTE)));
}
3、设置lazy-init属性
String lazyInit = ele.getAttribute(LAZY_INIT_ATTRIBUTE);
if (DEFAULT_VALUE.equals(lazyInit)) {
lazyInit = this.defaults.getLazyInit();
}
bd.setLazyInit(TRUE_VALUE.equals(lazyInit));
4、设置autowire属性
String autowire = ele.getAttribute(AUTOWIRE_ATTRIBUTE);
bd.setAutowireMode(getAutowireMode(autowire));
5、设置depends-on属性
if (ele.hasAttribute(DEPENDS_ON_ATTRIBUTE)) {
String dependsOn = ele.getAttribute(DEPENDS_ON_ATTRIBUTE);
bd.setDependsOn(StringUtils.tokenizeToStringArray(dependsOn, MULTI_VALUE_ATTRIBUTE_DELIMITERS));
}
6、设置autowire-candidate属性
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));
}
7、设置primary属性
if (ele.hasAttribute(PRIMARY_ATTRIBUTE)) {
bd.setPrimary(TRUE_VALUE.equals(ele.getAttribute(PRIMARY_ATTRIBUTE)));
}
8、设置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);
}
9、设置destroy-method属性
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);
}
10、设置factory-method属性
if (ele.hasAttribute(FACTORY_METHOD_ATTRIBUTE)) {
bd.setFactoryMethodName(ele.getAttribute(FACTORY_METHOD_ATTRIBUTE));
}
11、设置factory-bean属性
if (ele.hasAttribute(FACTORY_BEAN_ATTRIBUTE)) {
bd.setFactoryBeanName(ele.getAttribute(FACTORY_BEAN_ATTRIBUTE));
}
return bd;
}
代码块六:parseConstructorArgElements
public void parseConstructorArgElements(Element beanEle, BeanDefinition bd) {
1、拿到所有子节点
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)) {
2、解析constructor-arg节点
parseConstructorArgElement((Element) node, bd);
}
}
}
2、解析constructor-arg节点见代码块七
代码块七:parseConstructorArgElement
public void parseConstructorArgElement(Element ele, BeanDefinition bd) {
1.1、获取index属性
String indexAttr = ele.getAttribute(INDEX_ATTRIBUTE);
1.2、获取type属性
String typeAttr = ele.getAttribute(TYPE_ATTRIBUTE);
1.2获取name属性
String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
if (StringUtils.hasLength(indexAttr)) {
try {
int index = Integer.parseInt(indexAttr);
if (index < 0) {
error("'index' cannot be lower than 0", ele);
}
else {
try {
this.parseState.push(new ConstructorArgumentEntry(index));
2、解析属性值 包括子节点的
Object value = parsePropertyValue(ele, bd, null);
2.1、解析后的数据封装到ConstructorArgumentValues.ValueHolder中
ConstructorArgumentValues.ValueHolder valueHolder = new ConstructorArgumentValues.ValueHolder(value);
if (StringUtils.hasLength(typeAttr)) {
2.2、设置type属性
valueHolder.setType(typeAttr);
}
if (StringUtils.hasLength(nameAttr)) {
2.3、设置name属性
valueHolder.setName(nameAttr);
}
valueHolder.setSource(extractSource(ele));
2.4判断index是否重复
if (bd.getConstructorArgumentValues().hasIndexedArgumentValue(index)) {
error("Ambiguous constructor-arg entries for index " + index, ele);
}
else {
// 将index和valueHolder以key-value形式添加至当前BeanDefinition的constructorArgumentValues
// 的indexedArgumentValues属性中,(用于上面判断index是否重复指定)
bd.getConstructorArgumentValues().addIndexedArgumentValue(index, valueHolder);
}
}
finally {
this.parseState.pop();
}
}
}
catch (NumberFormatException ex) {
error("Attribute 'index' of tag 'constructor-arg' must be an integer", ele);
}
}
else {
try {
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));
3、与上面的indexedArgumentValues类似,上面有index存为map,这边没index存为list
bd.getConstructorArgumentValues().addGenericArgumentValue(valueHolder);
}
finally {
this.parseState.pop();
}
}
}
1.1先获取index、type、name的属性
2解析属性值 ref、value、list肯定包含其中一个见代码块八
2.4判断index是否重复,不重复则将 index 和 valueHolder 以 key-value 形式添加至当前BeanDefinition 的 constructorArgumentValues 的 indexedArgumentValues 属性中 。
代码块八:parsePropertyValue
@Nullable
public Object parsePropertyValue(Element ele, BeanDefinition bd, @Nullable String propertyName) {
String elementName = (propertyName != null) ?
"<property> element for property '" + propertyName + "'" :
"<constructor-arg> element";
// Should only have one child element: ref, value, list, etc.
// 应该只有 ref, value, list三个的其中一个
1、获取子节点 list、map等
NodeList nl = ele.getChildNodes();
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 {
1.1、找到子节点,赋值给subElement
subElement = (Element) node;
}
}
}
2.1、判断是ref吗
boolean hasRefAttribute = ele.hasAttribute(REF_ATTRIBUTE);
2.2、判断是value吗
boolean hasValueAttribute = ele.hasAttribute(VALUE_ATTRIBUTE);
2.3、不能同时存在,如果同时存在直接抛出异常
if ((hasRefAttribute && hasValueAttribute) ||
((hasRefAttribute || hasValueAttribute) && subElement != null)) {
error(elementName +
" is only allowed to contain either 'ref' attribute OR 'value' attribute OR sub-element", ele);
}
if (hasRefAttribute) {
3、处理ref属性,把它放到RuntimeBeanReference,相当于一个临时的容器当我们用的时候去解析成真正的bean实例。
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;
}
else if (hasValueAttribute) {
4、处理value属性,用TypedStringValue封装
TypedStringValue valueHolder = new TypedStringValue(ele.getAttribute(VALUE_ATTRIBUTE));
valueHolder.setSource(extractSource(ele));
return valueHolder;
}
else if (subElement != null) {
5、解析子节点 如list
return parsePropertySubElement(subElement, bd);
}
else {
6、都没有就直接抛出异常
// Neither child element nor "ref" or "value" attribute found.
error(elementName + " must specify a ref or value", ele);
return null;
}
}
先解析属性值,value或ref属性,如果没有解析子节点。
5、解析子节点见代码块九
代码块九:parsePropertySubElement
@Nullable
public Object parsePropertySubElement(Element ele, @Nullable BeanDefinition bd) {
return parsePropertySubElement(ele, bd, null);
}
@Nullable
public Object parsePropertySubElement(Element ele, @Nullable BeanDefinition bd, @Nullable String defaultValueType) {
1、如果不是默认的命名空间就去定制方法进行解析
if (!isDefaultNamespace(ele)) {
return parseNestedCustomElement(ele, bd);
}
else if (nodeNameEquals(ele, BEAN_ELEMENT)) {
2、子节点是bean会递归解析bean的方法
BeanDefinitionHolder nestedBd = parseBeanDefinitionElement(ele, bd);
if (nestedBd != null) {
nestedBd = decorateBeanDefinitionIfRequired(ele, nestedBd, bd);
}
return nestedBd;
}
else if (nodeNameEquals(ele, REF_ELEMENT)) {
// A generic reference to any name of any bean.
3、子节点是ref会和处理属性一样封装到临时的RuntimeBeanReference在真正解析的时候实例化。
String refName = ele.getAttribute(BEAN_REF_ATTRIBUTE);
boolean toParent = false;
if (!StringUtils.hasLength(refName)) {
// A reference to the id of another bean in a parent context.
refName = ele.getAttribute(PARENT_REF_ATTRIBUTE);
toParent = true;
if (!StringUtils.hasLength(refName)) {
error("'bean' or 'parent' is required for <ref> element", ele);
return null;
}
}
if (!StringUtils.hasText(refName)) {
error("<ref> element contains empty target attribute", ele);
return null;
}
RuntimeBeanReference ref = new RuntimeBeanReference(refName, toParent);
ref.setSource(extractSource(ele));
return ref;
}
else if (nodeNameEquals(ele, IDREF_ELEMENT)) {
4、解析idref
return parseIdRefElement(ele);
}
else if (nodeNameEquals(ele, VALUE_ELEMENT)) {
5、解析value
return parseValueElement(ele, defaultValueType);
}
else if (nodeNameEquals(ele, NULL_ELEMENT)) {
6、直接设置为null返回
// 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)) {
7、解析array
return parseArrayElement(ele, bd);
}
else if (nodeNameEquals(ele, LIST_ELEMENT)) {
8、解析list
return parseListElement(ele, bd);
}
else if (nodeNameEquals(ele, SET_ELEMENT)) {
9、解析set
return parseSetElement(ele, bd);
}
else if (nodeNameEquals(ele, MAP_ELEMENT)) {
10、解析map
return parseMapElement(ele, bd);
}
else if (nodeNameEquals(ele, PROPS_ELEMENT)) {
11、解析prop
return parsePropsElement(ele);
}
else {
12、都没有抛出异常
error("Unknown property sub-element: [" + ele.getNodeName() + "]", ele);
return null;
}
}
2、解析bean节点前面已经介绍过了见代码块四
5、解析value节点见代码块十
8、解析list节点见代码块十二
代码块十:parseValueElement
public Object parseValueElement(Element ele, @Nullable String defaultTypeName) {
// It's a literal value.
String value = DomUtils.getTextValue(ele);
String specifiedTypeName = ele.getAttribute(TYPE_ATTRIBUTE);
String typeName = specifiedTypeName;
if (!StringUtils.hasText(typeName)) {
//如果没有就用默认的类型
typeName = defaultTypeName;
}
try {
1、构建TypedStringValue
TypedStringValue typedValue = buildTypedStringValue(value, typeName);
typedValue.setSource(extractSource(ele));
typedValue.setSpecifiedTypeName(specifiedTypeName);
return typedValue;
}
catch (ClassNotFoundException ex) {
error("Type class [" + typeName + "] not found for <value> element", ele, ex);
return value;
}
}
1、构建TypedStringValue见代码块十一
代码块十一:buildTypedStringValue
protected TypedStringValue buildTypedStringValue(String value, @Nullable String targetTypeName)
throws ClassNotFoundException {
ClassLoader classLoader = this.readerContext.getBeanClassLoader();
TypedStringValue typedValue;
if (!StringUtils.hasText(targetTypeName)) {
1、如果没有设置类型直接new
typedValue = new TypedStringValue(value);
}
else if (classLoader != null) {
2、类加载器和targetTypeName不为空,通过反射创建该类型的类
Class<?> targetType = ClassUtils.forName(targetTypeName, classLoader);
typedValue = new TypedStringValue(value, targetType);
}
else {
3、使用value 和 type来构建
typedValue = new TypedStringValue(value, targetTypeName);
}
return typedValue;
}
代码块十二:parseListElement
public List<Object> parseListElement(Element collectionEle, @Nullable BeanDefinition bd) {
1、获取list的value-type属性,就是list节点下value的类型
String defaultElementType = collectionEle.getAttribute(VALUE_TYPE_ATTRIBUTE);
2、获取所有的子节点,一般为value
NodeList nl = collectionEle.getChildNodes();
3、用来存放节点的值
ManagedList<Object> target = new ManagedList<>(nl.getLength());
target.setSource(extractSource(collectionEle));
target.setElementTypeName(defaultElementType);
target.setMergeEnabled(parseMergeAttribute(collectionEle));
4、解析子节点集合
parseCollectionElements(nl, target, bd, defaultElementType);
return target;
}
protected void parseCollectionElements(
NodeList elementNodes, Collection<Object> target, @Nullable BeanDefinition bd, String defaultElementType) {
for (int i = 0; i < elementNodes.getLength(); i++) {
Node node = elementNodes.item(i);
if (node instanceof Element && !nodeNameEquals(node, DESCRIPTION_ELEMENT)) {
5、递归的去解析子节点的方法 这儿一般会进入解析value的方法
target.add(parsePropertySubElement((Element) node, bd, defaultElementType));
}
}
}
到这儿 constructor-arg已经解析完毕,回到代码块四继续解析。
代码块十三:parsePropertyElements
public void parsePropertyElements(Element beanEle, BeanDefinition bd) {
NodeList nl = beanEle.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
if (isCandidateElement(node) && nodeNameEquals(node, PROPERTY_ELEMENT)) {
1、 解析property节点
parsePropertyElement((Element) node, bd);
}
}
}
public void parsePropertyElement(Element ele, BeanDefinition bd) {
1、获取name属性
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 {
//校验在相同bean节点下,是否存在相同的name属性,如果存在则抛出异常
if (bd.getPropertyValues().contains(propertyName)) {
error("Multiple 'property' definitions for property '" + propertyName + "'", ele);
return;
}
2、解析属性 见代码块八
Object val = parsePropertyValue(ele, bd, propertyName);
PropertyValue pv = new PropertyValue(propertyName, val);
3、解析meta属性
parseMetaElements(ele, pv);
pv.setSource(extractSource(ele));
//用于重复校验
bd.getPropertyValues().addPropertyValue(pv);
}
finally {
this.parseState.pop();
}
}
2、解析属性见代码块八
我们回到代码块二继续讲解开始进入registerBeanDefinition方法。
代码块十四:registerBeanDefinition
public static void registerBeanDefinition(
BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
throws BeanDefinitionStoreException {
// Register bean definition under primary name.
1、获取要注册的name
String beanName = definitionHolder.getBeanName();
2、注册beanName、BeanDefinition到缓存中(核心逻辑),实现类为; DefaultListableBeanFactory
registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
// Register aliases for bean name, if any.
String[] aliases = definitionHolder.getAliases();
if (aliases != null) {
for (String alias : aliases) {
3、注册别名到aliasMap缓存中
registry.registerAlias(beanName, alias);
}
}
}
2、注册beanName、BeanDefinition到缓存中见代码块十五
3、注册别名见代码块十六
代码块十五:registerBeanDefinition
@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
throws BeanDefinitionStoreException {
1.beanName和beanDefinition为空校验
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;
2、先尝试从缓存中获取
oldBeanDefinition = this.beanDefinitionMap.get(beanName);
if (oldBeanDefinition != null) {
if (!isAllowBeanDefinitionOverriding()) {
2.1、不允许注册相同名字的bean则直接抛出异常
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 (!beanDefinition.equals(oldBeanDefinition)) {
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 + "]");
}
}
2.2、放到缓存当中
this.beanDefinitionMap.put(beanName, beanDefinition);
}
else {
3、是否已经开始创建
if (hasBeanCreationStarted()) {
// Cannot modify startup-time collection elements anymore (for stable iteration)
synchronized (this.beanDefinitionMap) {
3.1、已经开始了,将beanName和beanDefinition放到map缓存当中,就是开始我们提到的重要缓存之一。
this.beanDefinitionMap.put(beanName, beanDefinition);
List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
updatedDefinitions.addAll(this.beanDefinitionNames);
updatedDefinitions.add(beanName);
this.beanDefinitionNames = updatedDefinitions;
if (this.manualSingletonNames.contains(beanName)) {
3.2、因为已经创建好了,所以把排序的manualSingletonNames移除beanName
Set<String> updatedSingletons = new LinkedHashSet<>(this.manualSingletonNames);
updatedSingletons.remove(beanName);
this.manualSingletonNames = updatedSingletons;
}
}
}
else {
// Still in startup registration phase
4、未开始直接放到缓存当中
this.beanDefinitionMap.put(beanName, beanDefinition);
this.beanDefinitionNames.add(beanName);
this.manualSingletonNames.remove(beanName);
}
this.frozenBeanDefinitionNames = null;
}
if (oldBeanDefinition != null || containsSingleton(beanName)) {
resetBeanDefinition(beanName);
}
}
到这儿注册完成,注册其实就是放到缓存当中,等需要实例的时候从缓存中获取然后利用反射进行实例化。回到代码块十四进入注册别名方法。
代码块十六:registerAlias
@Override
public void registerAlias(String name, String alias) {
Assert.hasText(name, "'name' must not be empty");
Assert.hasText(alias, "'alias' must not be empty");
// 1.如果别名和beanName相同,则不算别名,从aliasMap缓存中移除
if (alias.equals(name)) {
this.aliasMap.remove(alias);
}
else {
String registeredName = this.aliasMap.get(alias);
if (registeredName != null) {
if (registeredName.equals(name)) {
// An existing alias - no need to re-register
// 2.如果别名已经注册过,直接返回
return;
}
// 3.如果存在相同的别名,并且不允许别名覆盖,则抛出异常
if (!allowAliasOverriding()) {
throw new IllegalStateException("Cannot register alias '" + alias + "' for name '" +
name + "': It is already registered for name '" + registeredName + "'.");
}
}
// 4.检查name和alias是否存在循环引用。例如A的别名为B,B的别名为A
checkForAliasCircle(name, alias);
// 5.将别名和beanName的映射放到aliasMap缓存中
this.aliasMap.put(alias, name);
}
}
总结
我们可以重新梳理一下思路,我们首先将 xml 中的 bean 配置信息进行了解析,并构建了 AbstractBeanDefinition(GenericBeanDefinition) 对象来存放所有解析出来的属性。
然后,我们将 AbstractBeanDefinition 、beanName、aliasesArray 构建成 BeanDefinitionHolder 对象并返回。
最后,我们通过 BeanDefinitionHolder 将 BeanDefinition 和 beanName 注册到 BeanFactory 中,也就是存放到缓存中。
执行完 parseDefaultElement 方法,我们得到了两个重要的缓存:
beanDefinitionNames 缓存。
beanDefinitionMap 缓存。
这两个缓存在之后的 IoC 构建过程中会发挥很重要的作用,大家在这边先有个印象。