参考博客:https://blog.csdn.net/sunchen2012/article/details/82415656
//解析Bean定义资源Document对象的普通元素
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
//将Element元素--->BeanDefinition的过程在此
//对Document对象中<Bean>元素的解析由BeanDefinitionParserDelegate实现
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele); //代码1
if (bdHolder != null) {
//修饰BeanDefinition
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
//主线
//向Spring IOC容器注册解析得到的Bean定义,这是Bean定义向IOC容器注册的入口
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
}
catch (BeanDefinitionStoreException ex) {
getReaderContext().error("Failed to register bean definition with name '" +
bdHolder.getBeanName() + "'", ele, ex);
}
//在完成向Spring IOC容器注册解析得到的Bean定义之后,发送注册事件
getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
}
}
代码1为解析DOM元素为BeanDefinition,具体操作如下。
由BeanDefinitionParserDelegate提供parseBeanDefinitionElement方法的实现:
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele) {
return parseBeanDefinitionElement(ele, null);
}
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) {
//获取id的值
String id = ele.getAttribute(ID_ATTRIBUTE);
//获取name的值,作为别名的
String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
List<String> aliases = new ArrayList<>();
if (StringUtils.hasLength(nameAttr)) {
//假如name字段有值,则进行解析操作,并添加到别名集合aliases中
//name的值可以用“,” “;” ",;" 分割,这里会解析为数组,当成多个别名使用
String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
aliases.addAll(Arrays.asList(nameArr));
}
//id作为bean的名称
String beanName = id;
if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {
//假如id为空,且别名不为空,则取首个别名作为beanName
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) {
//判断在当前<beans>中 是否有相同的名称
checkNameUniqueness(beanName, aliases, ele);
}
//调用重载方法 进行解析
//主线
AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
if (beanDefinition != null) {
//假如未声明别名和id的bean,则生成唯一的名称作为beanName
if (!StringUtils.hasText(beanName)) {
try {
if (containingBean != null) {
beanName = BeanDefinitionReaderUtils.generateBeanName(
beanDefinition, this.readerContext.getRegistry(), true);
}
else {
//生成一个“类名”+“#数字”的名称
beanName = this.readerContext.generateBeanName(beanDefinition);
//获取类名
String beanClassName = beanDefinition.getBeanClassName();
if (beanClassName != null &&
beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() &&
!this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {
//假如类名称未使用,则将类名作为当前bean的别名
aliases.add(beanClassName);
}
}
}
catch (Exception ex) {
error(ex.getMessage(), ele);
return null;
}
}
String[] aliasesArray = StringUtils.toStringArray(aliases);
//将BeanDefinition封装至BeanDefinitionHolder中,并返回
return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
}
return null;
}
继续到重载方法,看DOM元素解析过程:
public AbstractBeanDefinition parseBeanDefinitionElement(
Element ele, String beanName, @Nullable BeanDefinition containingBean) {
//将当前bean解析入栈,记录解析<bean>的过程,parseState可以通过toString来打印调用栈链
//下面解析property的时候,也同样记录了
this.parseState.push(new BeanEntry(beanName));
String className = null;
if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
}
String parent = null;
if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
parent = ele.getAttribute(PARENT_ATTRIBUTE);
}
try {
//根据类名和父类名创建BeanDefinition
AbstractBeanDefinition bd = createBeanDefinition(className, parent); //代码1
//解析DOM中的属性,并存入到AbstractBeanDefinition对象中
parseBeanDefinitionAttributes(ele, beanName, containingBean, bd); //代码2
//设置描述
bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));
//对<Bean>元素的meta(元信息)属性解析
parseMetaElements(ele, bd);
//对<Bean>元素的lookup-method属性解析
parseLookupOverrideSubElements(ele, bd.getMethodOverrides());