找入口

AbstractRefreshableApplicationContext类的refreshBeanFactory方法中第13行代码:

protected final void refreshBeanFactory() throws BeansException {
// 如果之前有IoC容器,则销毁
if (hasBeanFactory()) {
destroyBeans();
closeBeanFactory();
}
try {
// 创建IoC容器,也就是DefaultListableBeanFactory
DefaultListableBeanFactory beanFactory = createBeanFactory();
beanFactory.setSerializationId(getId());
customizeBeanFactory(beanFactory);
// 加载BeanDefinition对象,并注册到IoC容器中(重点)
loadBeanDefinitions(beanFactory);
synchronized (this.beanFactoryMonitor) {
this.beanFactory = beanFactory;
}
}
catch (IOException ex) {
throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
}
}

流程解析

  • 进入AbstractXmlApplicationContext的loadBeanDefinitions方法:

    • 创建一个XmlBeanDefinitionReader,通过阅读XML文件,真正完成BeanDefinition的加载和注册。
    • 配置XmlBeanDefinitionReader并进行初始化。
    • 委托给XmlBeanDefinitionReader去加载BeanDefinition。
 protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory)
throws BeansException, IOException {
// Create a new XmlBeanDefinitionReader for the given BeanFactory.
// 创建一个BeanDefinition阅读器,通过阅读XML文件,真正完成BeanDefinition的加载和注册
XmlBeanDefinitionReader beanDefinitionReader = new
XmlBeanDefinitionReader(beanFactory); // Configure the bean definition reader with this context's
// resource loading environment.
beanDefinitionReader.setEnvironment(this.getEnvironment());
beanDefinitionReader.setResourceLoader(this);
beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this)); // Allow a subclass to provide custom initialization of the reader,
// then proceed with actually loading the bean definitions.
initBeanDefinitionReader(beanDefinitionReader);
// 委托给BeanDefinition阅读器去加载BeanDefinition
loadBeanDefinitions(beanDefinitionReader);
} protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws
BeansException, IOException {
// 获取资源的定位
// 这里getConfigResources是一个空实现,真正实现是调用子类的获取资源定位的方法
// 比如:ClassPathXmlApplicationContext中进行了实现
// 而FileSystemXmlApplicationContext没有使用该方法
Resource[] configResources = getConfigResources();
if (configResources != null) {
// XML Bean读取器调用其父类AbstractBeanDefinitionReader读取定位的资源
reader.loadBeanDefinitions(configResources);
}
// 如果子类中获取的资源定位为空,则获取FileSystemXmlApplicationContext构造方法中setConfigLocations方法设置的资源
String[] configLocations = getConfigLocations();
if (configLocations != null) {
// XML Bean读取器调用其父类AbstractBeanDefinitionReader读取定位的资源
reader.loadBeanDefinitions(configLocations);
}
}
  • loadBeanDefinitions方法经过一路的兜兜转转,最终来到了XmlBeanDefinitionReaderdoLoadBeanDefinitions方法:

    • 一个是对XML文件进行DOM解析;
    • 一个是完成BeanDefinition对象的加载与注册
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
throws BeanDefinitionStoreException {
try {
// 通过DOM4J加载解析XML文件,最终形成Document对象
Document doc = doLoadDocument(inputSource, resource);
// 通过对Document对象的操作,完成BeanDefinition的加载和注册工作
return registerBeanDefinitions(doc, resource);
}
//省略一些catch语句
catch (Throwable ex) {
......
}
}
  • 此处我们暂不处理DOM4J加载解析XML的流程,我们重点分析BeanDefinition的加载注册流程
  • 进入XmlBeanDefinitionReaderregisterBeanDefinitions方法:
    • 创建DefaultBeanDefinitionDocumentReader用来解析Document对象。
    • 获得容器中已注册的BeanDefinition数量
    • 委托给DefaultBeanDefinitionDocumentReader来完成BeanDefinition的加载、注册工作。
    • 统计新注册的BeanDefinition数量
public int registerBeanDefinitions(Document doc, Resource resource) throws
BeanDefinitionStoreException {
// 创建DefaultBeanDefinitionDocumentReader用来解析Document对象
BeanDefinitionDocumentReader documentReader =
createBeanDefinitionDocumentReader();
// 获得容器中注册的Bean数量
int countBefore = getRegistry().getBeanDefinitionCount();
//解析过程入口,BeanDefinitionDocumentReader只是个接口
//具体的实现过程在DefaultBeanDefinitionDocumentReader完成
documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
// 统计注册的Bean数量
return getRegistry().getBeanDefinitionCount() - countBefore;
}
  • 进入DefaultBeanDefinitionDocumentReaderregisterBeanDefinitions方法:

    • 获得Document的根元素标签
    • 真正实现BeanDefinition解析和注册工作
 public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext
{
this.readerContext = readerContext;
logger.debug("Loading bean definitions");
// 获得Document的根元素<beans>标签
Element root = doc.getDocumentElement();
// 真正实现BeanDefinition解析和注册工作
doRegisterBeanDefinitions(root);
}
  • 进入DefaultBeanDefinitionDocumentReaderdoRegisterBeanDefinitions方法:

    • 这里使用了委托模式,将具体的BeanDefinition解析工作交给了BeanDefinitionParserDelegate去完成
    • 在解析Bean定义之前,进行自定义的解析,增强解析过程的可扩展性
    • 委托给BeanDefinitionParserDelegate,从Document的根元素开始进行BeanDefinition的解析
    • 在解析Bean定义之后,进行自定义的解析,增加解析过程的可扩展性
 protected void doRegisterBeanDefinitions(Element root) {
// Any nested <beans> elements will cause recursion in this method. In
// order to propagate and preserve <beans> default-* attributes correctly,
// keep track of the current (parent) delegate, which may be null. Create
// the new (child) delegate with a reference to the parent for fallback purposes,
// then ultimately reset this.delegate back to its original (parent) reference.
// this behavior emulates a stack of delegates without actually necessitating one. // 这里使用了委托模式,将具体的BeanDefinition解析工作交给了BeanDefinitionParserDelegate去完成
BeanDefinitionParserDelegate parent = this.delegate;
this.delegate = createDelegate(getReaderContext(), root, parent); if (this.delegate.isDefaultNamespace(root)) {
String profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);
if (StringUtils.hasText(profileSpec)) {
String[] specifiedProfiles = StringUtils.tokenizeToStringArray(
profileSpec, BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);
if (!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)) {
if (logger.isInfoEnabled()) {
logger.info("Skipped XML bean definition file due to specified profiles [" + profileSpec +
"] not matching: " + getReaderContext().getResource());
}
return;
}
}
}
// 在解析Bean定义之前,进行自定义的解析,增强解析过程的可扩展性
preProcessXml(root);
// 委托给BeanDefinitionParserDelegate,从Document的根元素开始进行BeanDefinition的解析
parseBeanDefinitions(root, this.delegate);
// 在解析Bean定义之后,进行自定义的解析,增加解析过程的可扩展性
postProcessXml(root); this.delegate = parent;
}
05-11 14:05