Spring源码解析 XML方式加载bean

继承图

Spring源码拥有的类实在太多了,所以梳理下主要的类图对研究代码还是很有用的,Spring的配置从先前的XML的配置的容器ClassPathXmlApplicationContext,到现在的基于注解的AnnotationConfigApplicationContext容器,都在下图展现。
在这里插入图片描述

加载Bean

我们本次内容主要探究下,Spring如何通过xml读取Bean容器,无论基于注解还是XML,都有一个比较重要的方法就是AbstractApplicationContext抽象容器的refresh()方法。下面的代码建议对照上面的类图去看,这样会印象深一些。

//AbstractApplicationContext 类
public void refresh() throws BeansException, IllegalStateException {
    .....
	ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
    .....
}

//AbstractRefreshableApplicationContext 类
protected final void refreshBeanFactory() throws BeansException {
        .....
		DefaultListableBeanFactory beanFactory = createBeanFactory();
        /** 这里的beanFactory是DefaultListableBeanFactory 
        同时抽象方法loadBeanDefinitions 由子类自定义去实现 **/
		loadBeanDefinitions(beanFactory);
		 .....
}

//AbstractXmlApplicationContext 类
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
     .....
     XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
     ...
     loadBeanDefinitions(beanDefinitionReader);
     .....
}

  1. 通过上面的各种过程调用,具体的加载bean定义会交给Bean读取对象XmlBeanDefinitionReader 去处理,XmlBeanDefinitionReader继承自AbstractBeanDefinitionReader
  2. 我们的这个抽象对象AbstractBeanDefinitionReader组合了BeanDefinitionRegistry接口属性。
    注意:DefaultListableBeanFactory实现了这个BeanDefinitionRegistry接口,最后我们会发现,维护Bean定义对象集合的正是这个DefaultListableBeanFactory
  3. DefaultBeanDefinitionDocumentReader里面的processBeanDefinition其实就包含了将读取的文件转化成
    BeanDefinitionHolder对象的过程,所以这个方法其实是我们最重要的方法体。
    BeanDefinitionHolder对象包含了私有属性BeanDefinition。我们后面就是对这个BeanDefinitionHolder的处理
//DefaultBeanDefinitionDocumentReader类
protected void doRegisterBeanDefinitions(Element root) {
	 ....
	 parseBeanDefinitions(root, this.delegate);
	 ....
}
//DefaultBeanDefinitionDocumentReader类
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
		//开始组建BeanDefinitionHolder对象
		BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
		if (bdHolder != null) {
			bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
			try {
				// 这里其实就是开始调我们的DefaultListableBeanFactory去处理
                BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
                //这里getRegistry()就是之前在XmlBeanDefinitionReader类里的DefaultListableBeanFactory的Registry对象
			}
			catch (BeanDefinitionStoreException ex) {
				getReaderContext().error("Failed to register bean definition with name '" +
						bdHolder.getBeanName() + "'", ele, ex);
			}
			// Send registration event.
			getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
		}
	}

4.最后会将解析的BeanDefinitionHolder存到我们DefaultListableBeanFactory,这里面的源码如下

//DefaultListableBeanFactory 类

/** 里面属性 Map of bean definition objects, keyed by bean name. */
private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
//主要的方法
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition){ 
   .....
   this.beanDefinitionMap.put(beanName, beanDefinition);
   	.....
}

在这里插入图片描述

后记

对于阅读源码还是不求甚解,浅尝辄止最好,以免调入调用的黑洞里面去,难以自拔。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章