如何解析 <bean> 的内容?
继续看代码:
public class BeanDefinitionParserDelegate {
public AbstractBeanDefinition parseBeanDefinitionElement(
Element ele, String beanName, @Nullable BeanDefinition containingBean) {
String className = null;
// 读取 <bean> 标签的 class 属性
if (ele.hasAttribute(CLASS_ATTRIBUTE)) {
className = ele.getAttribute(CLASS_ATTRIBUTE).trim();
}
String parent = null;
// 读取 <bean> 标签的 parent 属性
if (ele.hasAttribute(PARENT_ATTRIBUTE)) {
parent = ele.getAttribute(PARENT_ATTRIBUTE);
}
try {
// 创建 BeanDefinition 对象(GenericBeanDefinition)
AbstractBeanDefinition bd = createBeanDefinition(className, parent);
// 解析 scope、lazy-init、autowire 等属性
parseBeanDefinitionAttributes(ele, beanName, containingBean, bd);
bd.setDescription(DomUtils.getChildElementValueByTagName(ele, DESCRIPTION_ELEMENT));
// 解析 meta 标签
parseMetaElements(ele, bd);
// 解析 lookup-method 标签
parseLookupOverrideSubElements(ele, bd.getMethodOverrides());
// 解析 replace-method 标签
parseReplacedMethodSubElements(ele, bd.getMethodOverrides());
// 解析 constructor-arg 标签
parseConstructorArgElements(ele, bd);
// 解析 property 标签
parsePropertyElements(ele, bd);
// 解析 qualifier 标签
parseQualifierElements(ele, bd);
bd.setResource(this.readerContext.getResource());
bd.setSource(extractSource(ele));
return bd;
}
// catch ...
return null;
}
}
这里才是真正解析 <bean> 标签内容的地方,比如常见的 class、parent、scope、lazy-init、autowire、property、constructor-arg 等,还有不常见的 lookup-method、replace-method 等。
该方法内部调用了一个个方法去解析不同的标签。这里我们只跟进常见的 property 如何解析,其他方法大体也都差不多,有兴趣可以自行研究。
parsePropertyElements 方法代码如下:
public class BeanDefinitionParserDelegate {
// 解析 property 标签
public void parsePropertyElements(Element beanEle, BeanDefinition bd) {
NodeList nl = beanEle.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
// 筛选 <property> 标签
if (isCandidateElement(node) && nodeNameEquals(node, PROPERTY_ELEMENT)) {
parsePropertyElement((Element) node, bd);
}
}
}
public void parsePropertyElement(Element ele, BeanDefinition bd) {
// property 标签的 name 属性
String propertyName = ele.getAttribute(NAME_ATTRIBUTE);
if (!StringUtils.hasLength(propertyName)) {
// error
return;
}
this.parseState.push(new PropertyEntry(propertyName));
try {
if (bd.getPropertyValues().contains(propertyName)) {
// error