目录
1 parseBeanDefinitionElement方法
2 decorateBeanDefinitionIfRequired方法
在parseDefaultElement中,可以看到,默认标签共有四种,其中做关键的当然是bean标签。所以下面就以Bean为例说明默认标签的解析。
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
if (delegate.nodeNameEquals(ele, "import")) {
this.importBeanDefinitionResource(ele);
} else if (delegate.nodeNameEquals(ele, "alias")) {
this.processAliasRegistration(ele);
} else if (delegate.nodeNameEquals(ele, "bean")) {
this.processBeanDefinition(ele, delegate);
} else if (delegate.nodeNameEquals(ele, "beans")) {
this.doRegisterBeanDefinitions(ele);
}
}
首先看processBeanDefinition源码:
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, this.getReaderContext().getRegistry());
} catch (BeanDefinitionStoreException var5) {
this.getReaderContext().error("Failed to register bean definition with name '" + bdHolder.getBeanName() + "'", ele, var5);
}
this.getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
}
}
程序逻辑为:
- 首先调用BeanDefinitionParserDelegate类的parseBeanDefinitionElement方法,对传入的DOM元素进行解析。将解析到的各种属性封装进BeanDefinitionHolder对象
- 如果上一步返回的BeanDefinitionHolder对象不为空,则进一步处理。假如默认标签的节点内包含了自定义标签,还需要调用decorateBeanDefinitionIfRequired方法进一步解析
- 然后进行BeanDefinition的注册
- 最后触发加载完成事件,以便相关监听器进行后续处理
1 parseBeanDefinitionElement方法
该方法源码如下:
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, @Nullable BeanDefinition containingBean) {
String id = ele.getAttribute("id");
String nameAttr = ele.getAttribute("name");
List<String> aliases = new ArrayList();
if (StringUtils.hasLength(nameAttr)) {
String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, ",; ");
aliases.addAll(Arrays.asList(nameArr));
}
String beanName = id;
if (!StringUtils.hasText(id) && !aliases.isEmpty()) {
beanName = (String)aliases.remove(0);
}
if (containingBean == null) {
this.checkNameUniqueness(beanName, aliases, ele);
}
AbstractBeanDefinition beanDefinition = this.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);
String beanClassName = beanDefinition.getBeanClassName();
if (beanClassName != null && beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() && !this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {
aliases.add(beanClassName);
}
}
} catch (Exception var9) {
this.error(var9.getMessage(), ele);
return null;
}
}
String[] aliasesArray = StringUtils.toStringArray(aliases);
return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
} else {
return null;
}
}
该方法首先解析出id和name属性,并将id作为Bean的唯一不可重复名称,name作为Bean的别名,从代码可以看出,name可以配置多个值,用逗号分隔。假如没有设置id,则取第一个name作为BeanName。然后在parseBeanDefinitionElement的重载方法中,进一步解析class、parent等属性,并进行BeanDefinition的组装,如果id和name都没有指定,则调用generateBeanName生成一个。最后,将生成的BeanDefinition和BeanName、AliasArray封装进BeanDefinitionHolder。
parseBeanDefinitionElement的重载版本解析过程如下(catch块省略),各个流程都加了注释:
public AbstractBeanDefinition parseBeanDefinitionElement(Element ele, String beanName, @Nullable BeanDefinition containingBean) {
this.parseState.push(new BeanEntry(beanName));
//解析class属性
String className = null;
if (ele.hasAttribute("class")) {
className = ele.getAttribute("class").trim();
}
//解析parent属性
String parent = null;
if (ele.hasAttribute("parent")) {
parent = ele.getAttribute("parent");
}
try {
//BeanDefinition组装过程
AbstractBeanDefinition bd = this.createBeanDefinition(className, parent);
//解析其他属性
this.parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
bd.setDescription(DomUtils.getChildElementValueByTagName(ele, "description"));
//解析元数据
this.parseMetaElements(ele, bd);
//解析look-up属性
this.parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
//解