第6讲中的代码块1中的parseBeanDefinitions(root, this.delegate)方法解析:
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
if (delegate.isDefaultNamespace(root)) {
NodeList nl = root.getChildNodes();
for (int i = 0; i < nl.getLength(); i++) {
Node node = nl.item(i);
if (node instanceof Element) {
Element ele = (Element) node;
if (delegate.isDefaultNamespace(ele)) {
//解析默认的元素(详解见:内部代码块1)
parseDefaultElement(ele, delegate);
}
else {
delegate.parseCustomElement(ele);
}
}
}
}
else {
delegate.parseCustomElement(root);
}
}
内部代码块1:
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
//对import标签的解析
if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
importBeanDefinitionResource(ele);
}
//对alias标签的解析
else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
processAliasRegistration(ele);
}
//对bean标签的解析
else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
//这里 详解见:内部代码块2)
processBeanDefinition(ele, delegate);
}
//对beans标签的解析
else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
// recurse
doRegisterBeanDefinitions(ele);
}
}
内部代码块2:
//下面只是总结这个方法的作用,如果有兴趣可以进入方法深入研究,我这里为了简单就不深入展示代码了
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
//这个方法就是真正创建BeanDefinition的方法,只是spring通过BeanDefinitionHolder把BeanDefinition包装了一层
BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
if (bdHolder != null) {
//对BeanDefinition进行包装,如果有需要的话(这里面会查找出元素的子元素,如<bean>元素的<property name="name" value=""></property>,然后会把子元素赋值到该BeanDefinition里面去)
bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
try {
// Register the final decorated instance.
//把BeanDefinition注册到IOC容器中去,IOC容器就是BeanFactory,意思就是把BeanDefinition注册到BeanFactory的Map<String, BeanDefinition>集合属性中,当然还有注册一些个其他的小属性,如把beanName也注册到List<String>集合中
BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
}
catch (BeanDefinitionStoreException ex) {
getReaderContext().error("Failed to register bean definition with name '" +
bdHolder.getBeanName() + "'", ele, ex);
}
// Send registration event.
//注册一个注册事件
getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
}
}
1、 w3c已经定义好了dom文档规范,spring内部对xml文档的解析就是引用的一些实现了w3c dom规范的实现方组件,如spirng就是应用的sax。说的更加直白,spring配置文件中定义的所有元素都会转换成一个一个Element对象,Element对象里面已经封装好了获取当前元素属性、获取当前元素父元素等一些列方法(其实是因为Element继承了Node接口,这些方法都定义在了Node接口中)。
2、我发现xml中的元素存在继承关系,如:beans标签里面定义的所有标签(如bean)都会把beans标签的命名空间给继承下来,当spring对一个元素进行解析的时候,会先对元素的命名空间进行判断,如果是默认的命名空间(beans标签的命名空间)就会执行对默认命名空间元素的解析方法。如果不是默认的命名空间,就会执行的自定义命名空间的解析方法
3、BeanDefinition
spring首先会把所有的元素定义成一个一个的BeanDefinition对象,spring并没有直接实例化出一个对象,而是通过该对象,来保存某个Bean的所有信息。里面有很多保存了bean的很多属性,有个重要的属性就是:private volatile Object beanClass ,spring会根据bean的class属性是否存在和类加载器是否存在这两个条件来判断是否需要创建出bean的Class对象。如果有类加载器就创建出Class对象,并且保存到beanClass 这个属性中。如果不存在类加载器就直接把class属性保存到beanClass属性中。BeanDefinition的其他属性的赋值过程是:先在构造函数中赋默认值,然后在把元素对象Element中的值赋值给BeanDefinition对象