XmlWebApplicationContext加载bean XML源码解析

XmlWebApplicationContext是我们开发中用到的最多的ApplicationContext实现,我对其源代码详细的分析,以便以后复习的时候可以参考。
public class XmlWebApplicationContext extends AbstractRefreshableWebApplicationContext {
   
/** Default config location for the root context */
   
public static final String DEFAULT_CONFIG_LOCATION = " /WEB-INF/applicationContext.xml " ;
   
/** Default prefix for building a config location for a namespace */
   
public static final String DEFAULT_CONFIG_LOCATION_PREFIX = " /WEB-INF/ " ;
   
/** Default suffix for building a config location for a namespace */
   
public static final String DEFAULT_CONFIG_LOCATION_SUFFIX = " .xml " ;

   
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws IOException {
       
// 创建BeanDefinitionReader,从XML中读取bean信息的读取器
        XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
        beanDefinitionReader.setResourceLoader(
this );
        beanDefinitionReader.setEntityResolver(
new ResourceEntityResolver( this ));

        initBeanDefinitionReader(beanDefinitionReader);
        loadBeanDefinitions(beanDefinitionReader);
    }

   
protected void initBeanDefinitionReader(XmlBeanDefinitionReader beanDefinitionReader) {
    }

   
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
        String[] configLocations
= getConfigLocations();
       
if (configLocations != null ) {
           
for ( int i = 0 ; i < configLocations.length; i ++ ) {
                reader.loadBeanDefinitions(configLocations[i]);
            }
        }
    }

   
protected String[] getDefaultConfigLocations() {
       
if (getNamespace() != null ) {
           
return new String[] {DEFAULT_CONFIG_LOCATION_PREFIX + getNamespace() +                              DEFAULT_CONFIG_LOCATION_SUFFIX};
        }
       
else {
           
return new String[] {DEFAULT_CONFIG_LOCATION};
        }
    }

}

loadBeanDefinitions(String location)方法是在AbstractBeanDefinitionReader中实现的:

    public int loadBeanDefinitions(String location) throws BeanDefinitionStoreException {
        ResourceLoader resourceLoader
= getResourceLoader();
       
if (resourceLoader == null ) {
           
throw new BeanDefinitionStoreException(
                   
" Cannot import bean definitions from location [ " + location + " ]: no ResourceLoader available " );
        }

       
if (resourceLoader instanceof ResourcePatternResolver) {
           
// Resource pattern matching available.
            try {
                Resource[] resources
= ((ResourcePatternResolver) resourceLoader).getResources(location);
               
int loadCount = loadBeanDefinitions(resources);
               
if (logger.isDebugEnabled()) {
                    logger.debug(
" Loaded " + loadCount + " bean definitions from location pattern [ " + location + " ] " );
                }
               
return loadCount;
            }
           
catch (IOException ex) {
               
throw new BeanDefinitionStoreException(
                       
" Could not resolve bean definition resource pattern [ " + location + " ] " , ex);
            }
        }
       
else {
           
// 根据给定的路径获得Resource.
            Resource resource = resourceLoader.getResource(location);
            //根据XML文件的bean信息加载bean属性
           
int loadCount = loadBeanDefinitions(resource);
           
if (logger.isDebugEnabled()) {
                logger.debug(
" Loaded " + loadCount + " bean definitions from location [ " + location + " ] " );
            }
           
return loadCount;
        }
    }

这儿,public int loadBeanDefinitions(Resource resource)方法是在其子类XmlBeanDefinitionReader中实现的:


   
        //把XML中bean的配置信息注册到BeanDefinition中去
        documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
       
return getBeanFactory().getBeanDefinitionCount() - countBefore;
    }
public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
       
return loadBeanDefinitions( new EncodedResource(resource));
    }

   
public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException {
        Assert.notNull(encodedResource,
" EncodedResource must not be null " );
       
if (logger.isInfoEnabled()) {
            logger.info(
" Loading XML bean definitions from " + encodedResource.getResource());
        }

       
try {
           
// 过的XML配置文件的输入流
            InputStream inputStream = encodedResource.getResource().getInputStream();
           
try {
                InputSource inputSource
= new InputSource(inputStream);
               
if (encodedResource.getEncoding() != null ) {
                    inputSource.setEncoding(encodedResource.getEncoding());
                }
               
return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
            }
           
finally {
                inputStream.close();
            }
        }
       
catch (IOException ex) {
           
throw new BeanDefinitionStoreException(
                   
" IOException parsing XML document from " + encodedResource.getResource(), ex);
        }
    }

   
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
           
throws BeanDefinitionStoreException {
       
try {
           
int validationMode = getValidationModeForResource(resource);
            Document doc
= this .documentLoader.loadDocument(
                    inputSource,
this .entityResolver, this .errorHandler, validationMode, this .namespaceAware);
           
return registerBeanDefinitions(doc, resource);
        }
       
catch (BeanDefinitionStoreException ex) {
           
throw ex;
        }
       
catch (ParserConfigurationException ex) {
           
throw new BeanDefinitionStoreException(
                   
" Parser configuration exception parsing XML from " + resource, ex);
        }
       
catch (SAXParseException ex) {
           
throw new BeanDefinitionStoreException(
                   
" Line " + ex.getLineNumber() + " in XML document from " + resource + " is invalid " , ex);
        }
       
catch (SAXException ex) {
           
throw new BeanDefinitionStoreException( " XML document from " + resource + " is invalid " , ex);
        }
       
catch (IOException ex) {
           
throw new BeanDefinitionStoreException( " IOException parsing XML document from " + resource, ex);
        }
       
catch (Throwable ex) {
           
throw new BeanDefinitionStoreException( " Unexpected exception parsing XML document from " + resource, ex);
        }
    }

   
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
       
//使用 XmlBeanDefinitionParser读取配置文件,但是现在已经反对使用此类
        if ( this .parserClass != null ) {
            XmlBeanDefinitionParser parser
=
                    (XmlBeanDefinitionParser) BeanUtils.instantiateClass(
this .parserClass);
           
return parser.registerBeanDefinitions( this , doc, resource);
        }
       
//Spring2.0以后都用BeanDefinitionDocumentReader来读取
        BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
       
int countBefore = getBeanFactory().getBeanDefinitionCount();

BeanDefinitionDocumentReader有一个默认的实现类DefaultBeanDefinitionDocumentReader:

    public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
       
this .readerContext = readerContext;

        logger.debug(
" Loading bean definitions " );
        Element root
= doc.getDocumentElement();

        BeanDefinitionParserDelegate delegate
= createHelper(readerContext, root);

        preProcessXml(root);
        parseBeanDefinitions(root, delegate);
        postProcessXml(root);
    }
    //从根节点开始读取bean配置信息,并把属性一一复制到BeanDefinition中去
   
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
       
if (delegate.isDefaultNamespace(root.getNamespaceURI())) {
            NodeList nl
= root.getChildNodes();
           
for ( int i = 0 ; i < nl.getLength(); i ++ ) {
                Node node
= nl.item(i);
               
if (node instanceof Element) {
                    Element ele
= (Element) node;
                    String namespaceUri
= ele.getNamespaceURI();
                   
if (delegate.isDefaultNamespace(namespaceUri)) {
                        parseDefaultElement(ele, delegate);
                    }
                   
else {
                        delegate.parseCustomElement(ele);
                    }
                }
            }
        }
       
else {
            delegate.parseCustomElement(root);
        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值