找入口
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
方法经过一路的兜兜转转,最终来到了XmlBeanDefinitionReader的doLoadBeanDefinitions
方法:一个是对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的加载注册流程
- 进入XmlBeanDefinitionReader的
registerBeanDefinitions
方法:- 创建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; }
- 进入DefaultBeanDefinitionDocumentReader的
registerBeanDefinitions
方法:- 获得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); }
- 进入DefaultBeanDefinitionDocumentReader
doRegisterBeanDefinitions
方法:- 这里使用了委托模式,将具体的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; }