1.通过前两篇博客的分析,我们已经了解了Spring IoC容器定位和载入Bean定义资源文件的基本过程,接下来我们要继续分析Spring IoC容器将载入的Bean定义资源文件转换为Document对象之后,是如何将其解析为Spring IoC管理的Bean对象并将其注册到容器中的。
2.XmlBeanDefinitionReader解析载入的Bean定义资源文件:
XmlBeanDefinitionReader类中的doLoadBeanDefinitions方法是从特定XML文件中实际载入Bean定义资源的方法,该方法在载入Bean定义资源之后将其转换为Document对象,接下来调用registerBeanDefinitions启动Spring IoC容器对Bean定义的解析过程,registerBeanDefinitions方法源码如下:
[java]- //按照Spring的Bean语义要求将Bean定义资源解析并转换为容器内部数据结构 public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
- //得到BeanDefinitionDocumentReader来对xml格式的BeanDefinition解析 BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
- //获得容器中注册的Bean数量 int countBefore = getRegistry().getBeanDefinitionCount();
- //解析过程入口,这里使用了委派模式,BeanDefinitionDocumentReader只是个接口,//具体的解析实现过程有实现类DefaultBeanDefinitionDocumentReader完成 documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
- //统计解析的Bean数量 return getRegistry().getBeanDefinitionCount() - countBefore;
- } //创建BeanDefinitionDocumentReader对象,解析Document对象
- protected BeanDefinitionDocumentReader createBeanDefinitionDocumentReader() { return BeanDefinitionDocumentReader.class.cast(BeanUtils.instantiateClass(this.documentReaderClass));
- }
Bean定义资源的载入解析分为以下两个过程:
首先,通过调用XML解析器将Bean定义资源文件转换得到Document对象,但是这些Document对象并没有按照Spring的Bean规则进行解析。这一步是载入的过程
其次,在完成通用的XML解析之后,按照Spring的Bean规则对Document对象进行解析。
按照Spring的Bean规则对Document对象解析的过程是在接口BeanDefinitionDocumentReader的实现类DefaultBeanDefinitionDocumentReader中实现的。
3.DefaultBeanDefinitionDocumentReader对Bean定义的Document对象解析:
BeanDefinitionDocumentReader接口通过registerBeanDefinitions方法调用其实现类DefaultBeanDefinitionDocumentReader对Document对象进行解析,解析的代码如下:
[java]- //根据Spring DTD对Bean的定义规则解析Bean定义Document对象 public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
- //获得XML描述符 this.readerContext = readerContext;
- logger.debug(Loading bean definitions); //获得Document的根元素
- Element root = doc.getDocumentElement(); //具体的解析过程由BeanDefinitionParserDelegate实现,
- //BeanDefinitionParserDelegate中定义了Spring Bean定义XML文件的各种元素 BeanDefinitionParserDelegate delegate = createHelper(readerContext, root);
- //在解析Bean定义之前,进行自定义的解析,增强解析过程的可扩展性 preProcessXml(root);
- //从Document的根元素开始进行Bean定义的Document对象 parseBeanDefinitions(root, delegate);
- //在解析Bean定义之后,进行自定义的解析,增加解析过程的可扩展性 postProcessXml(root);
- } //创建BeanDefinitionParserDelegate,用于完成真正的解析过程
- protected BeanDefinitionParserDelegate createHelper(XmlReaderContext readerContext, Element root) { BeanDefinitionParserDelegate delegate = new BeanDefinitionParserDelegate(readerContext);
- //BeanDefinitionParserDelegate初始化Document根元素 delegate.initDefaults(root);
- return delegate; }
- //使用Spring的Bean规则从Document的根元素开始进行Bean定义的Document对象 protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
- //Bean定义的Document对象使用了Spring默认的XML命名空间 if (delegate.isDefaultNamespace(root)) {
- //获取Bean定义的Document对象根元素的所有子节点 NodeList nl = root.getChildNodes();
- for (int i = 0; i < nl.getLength(); i++) { Node node = nl.item(i);
- //获得Document节点是XML元素节点 if (node instanceof Element) {
- Element ele = (Element) node; //Bean定义的Document的元素节点使用的是Spring默认的XML命名空间
- if (delegate.