上文说到在解析具体的bean时候,会走到不同的分支,可能是parseDefaultElement,也可能是parseCustomElement,接下来看parseDefaultElement的机制。
this.parseDefaultElement(ele, delegate);
默认标签
首先进入到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);
}
可见, 主要对四种类型的node进行解析,分别是import、alias、bean、beans进行解析
- bean解析
- 首先进入到processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) 中, 委托BeanDefinitionDelegate类的parseBeanDefinitionElement 方法进行元素解析, 返回BeanDefinitionHolder实例。
- 获得element的id,name等参数
- 对name使用tokenizer截断(,;), 然后把这些截断的字符串加到alias中
- 如果id未定义但是alias数组不为空,则把alias中的第一个元素作为beanName, 否则, id就是beanName
- 然后检查beanName以及alias的唯一性 checkNameUniqueness
- parseBeanDefinitionElement: 获得BeanDefinition的定义
- 接上文所述,执行BeanDefinitionParserDelegate的parseBeanDefinitionElement(Element ele, String beanName, BeanDefinition containingBean)函数
- 把当前的解析状态放在parseState栈中
- 初始化:解析class属性和parent属性
- 创建BeanDefinition对象: 初始化beanClassName 和 parent属性
- 解析bean的一些属性:parseBeanDefinitionAttributes, scope、abstract、lazy-init、autowire、dependency-check、depends-on、autowire-candidate、primary、init-method、destroy-method、factory-method、factory-bean等属性
- 解析子元素metaData:解析诸如如下的情形
<bean id="as" class = "">
<meta key="key1" value="val1"/>
<meta key="key2" value= "val2" />
</bean>
- 配置lookup方法,(获取器注入) 这个方法主要在某些特定的情况下比较有用
举个例子:
有基类Base和Der1, Der2, 其中Der1和Der2都重写了Base类的work函数
然后有一个AbstractFactory类
abstract class AbstractFactory{
......
abstract Base getBase();
......
}
然后在context.xml中配置
<bean id="absBase" class="xxx.xxx.AbstractBase">
<lookup-method name="getBase" bean="der1"/>
</bean>
<bean id="der1" class="xxxx.xxx.Der1"/>
获得absBase bean之后,调用起getBase,就会得到Der1对象, 而随着业务逻辑的变化,可在这个bean中配置其他的Base继承类来实现,高度解耦
- 解析子元素replace-method:类似上面,提供一个替换函数的解决方案
首先定义一个Bean A, 然后定义一个CallBack 实现MethodReplacer,实现其reimplement函数,然后在险要替换函数的bean上加一个<replace-method标签,设置函数名称name以及replacer用来指定替换bean