protectedvoidloadBeanDefinitions(DefaultListableBeanFactory beanFactory)throwsBeansException,IOException{// Create a new XmlBeanDefinitionReader for the given BeanFactory.//xml 转化为 对应 实体对象 的 解析器XmlBeanDefinitionReader beanDefinitionReader =newXmlBeanDefinitionReader(beanFactory);// Configure the bean definition reader with this context's// resource loading environment.//设置系统环境
beanDefinitionReader.setEnvironment(this.getEnvironment());//设置资源加载器
beanDefinitionReader.setResourceLoader(this);//设置实体对象解析器 (主要作用是将xml中的bean标签解析成beanDefinition对象)
beanDefinitionReader.setEntityResolver(newResourceEntityResolver(this));// Allow a subclass to provide custom initialization of the reader,// then proceed with actually loading the bean definitions.//设置XmlBeanDefinitionReader 其他的一些属性值,子类可重写该方法initBeanDefinitionReader(beanDefinitionReader);//解析xml,将bean注册到Spring容器中loadBeanDefinitions(beanDefinitionReader);}
publicintloadBeanDefinitions(String... locations)throwsBeanDefinitionStoreException{Assert.notNull(locations,"Location array must not be null");int count =0;//返回总注册bean的数量//遍历所有的路径加载xmlfor(String location : locations){
count +=loadBeanDefinitions(location);}return count;}
publicintloadBeanDefinitions(String location,@NullableSet<Resource> actualResources)throwsBeanDefinitionStoreException{ResourceLoader resourceLoader =getResourceLoader();if(resourceLoader ==null){thrownewBeanDefinitionStoreException("Cannot load bean definitions from location ["+ location +"]: no ResourceLoader available");}//这里的resourceLoader 就是ClassPathXmlApplicationContext 并且继承 ResourcePatternResolverif(resourceLoader instanceofResourcePatternResolver){// Resource pattern matching available.try{//根据路径获取路径中的资源Resource[] resources =((ResourcePatternResolver) resourceLoader).getResources(location);//加载资源,并返回注册bean的数量int count =loadBeanDefinitions(resources);if(actualResources !=null){Collections.addAll(actualResources, resources);}if(logger.isTraceEnabled()){
logger.trace("Loaded "+ count +" bean definitions from location pattern ["+ location +"]");}return count;}catch(IOException ex){thrownewBeanDefinitionStoreException("Could not resolve bean definition resource pattern ["+ location +"]", ex);}}else{// Can only load single resources by absolute URL.Resource resource = resourceLoader.getResource(location);int count =loadBeanDefinitions(resource);if(actualResources !=null){
actualResources.add(resource);}if(logger.isTraceEnabled()){
logger.trace("Loaded "+ count +" bean definitions from location ["+ location +"]");}return count;}}
XmlBeanDefinitionReader#loadBeanDefinitions()方法
publicintloadBeanDefinitions(EncodedResource encodedResource)throwsBeanDefinitionStoreException{Assert.notNull(encodedResource,"EncodedResource must not be null");if(logger.isTraceEnabled()){
logger.trace("Loading XML bean definitions from "+ encodedResource);}//当前线程中是否已存在该资源,如果不存在则报错Set<EncodedResource> currentResources =this.resourcesCurrentlyBeingLoaded.get();if(currentResources ==null){
currentResources =newHashSet<>(4);this.resourcesCurrentlyBeingLoaded.set(currentResources);}if(!currentResources.add(encodedResource)){thrownewBeanDefinitionStoreException("Detected cyclic loading of "+ encodedResource +" - check your import definitions!");}try{//获取资源的输入流InputStream inputStream = encodedResource.getResource().getInputStream();try{//将输入流包装成sourceInputSource inputSource =newInputSource(inputStream);if(encodedResource.getEncoding()!=null){//设置source的字符集
inputSource.setEncoding(encodedResource.getEncoding());}//正真开始解析xmlreturndoLoadBeanDefinitions(inputSource, encodedResource.getResource());}finally{
inputStream.close();}}catch(IOException ex){thrownewBeanDefinitionStoreException("IOException parsing XML document from "+ encodedResource.getResource(), ex);}finally{
currentResources.remove(encodedResource);if(currentResources.isEmpty()){this.resourcesCurrentlyBeingLoaded.remove();}}}
protectedintdoLoadBeanDefinitions(InputSource inputSource,Resource resource)throwsBeanDefinitionStoreException{try{//将xml转成Document对象Document doc =doLoadDocument(inputSource, resource);//将document对象转成 beanDefinition,并且将其注册到Spring容器中int count =registerBeanDefinitions(doc, resource);if(logger.isDebugEnabled()){
logger.debug("Loaded "+ count +" bean definitions from "+ resource);}return count;}catch(BeanDefinitionStoreException ex){throw ex;}catch(SAXParseException ex){thrownewXmlBeanDefinitionStoreException(resource.getDescription(),"Line "+ ex.getLineNumber()+" in XML document from "+ resource +" is invalid", ex);}catch(SAXException ex){thrownewXmlBeanDefinitionStoreException(resource.getDescription(),"XML document from "+ resource +" is invalid", ex);}catch(ParserConfigurationException ex){thrownewBeanDefinitionStoreException(resource.getDescription(),"Parser configuration exception parsing XML from "+ resource, ex);}catch(IOException ex){thrownewBeanDefinitionStoreException(resource.getDescription(),"IOException parsing XML document from "+ resource, ex);}catch(Throwable ex){thrownewBeanDefinitionStoreException(resource.getDescription(),"Unexpected exception parsing XML document from "+ resource, ex);}}
protectedvoiddoRegisterBeanDefinitions(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.//真正处理从Document变为beanDefinition的类,解析各种标签BeanDefinitionParserDelegate parent =this.delegate;//创建解析beandefinition的处理类this.delegate =createDelegate(getReaderContext(), root, parent);//判断是否是默认命名空间if(this.delegate.isDefaultNamespace(root)){//获取profile 指定使用那种环境下的xmlString profileSpec = root.getAttribute(PROFILE_ATTRIBUTE);if(StringUtils.hasText(profileSpec)){String[] specifiedProfiles =StringUtils.tokenizeToStringArray(
profileSpec,BeanDefinitionParserDelegate.MULTI_VALUE_ATTRIBUTE_DELIMITERS);// We cannot use Profiles.of(...) since profile expressions are not supported// in XML config. See SPR-12458 for details.if(!getReaderContext().getEnvironment().acceptsProfiles(specifiedProfiles)){if(logger.isDebugEnabled()){
logger.debug("Skipped XML bean definition file due to specified profiles ["+ profileSpec +"] not matching: "+getReaderContext().getResource());}return;}}}//转换前置处理,子类可重写preProcessXml(root);//转换parseBeanDefinitions(root,this.delegate);//转换后置处理,子类可重写postProcessXml(root);this.delegate = parent;}