zoukankan      html  css  js  c++  java
  • Spring框架学习笔记----Spring框架如何读取xml文件里的bean?

    spring框架刚出来的时候,我们基本都是在 xml文件里配置bean的,那么spring框架是如何解析xml 里内容的呢,今天我们就从一句代码着手,一步步来分析。

    spring框架的其中一大特性IOC,讲的就是把bean的创建交给spring框架来做,这样能保证类之间互相引用时,不需要 new 一个对象,只需要使用注解注入即可引用对应的类。因此spring框架会把xml里定义的bean实例化。

    BeanFactory bf = new XmlBeanFactory(new ClassPathResource("bean.xml"))

    首先看 new ClassPathResource("bean.xml") 做了什么。

    public ClassPathResource(String path) {
            this(path, (ClassLoader) null);
        }
    
    public ClassPathResource(String path, @Nullable ClassLoader classLoader) {
            Assert.notNull(path, "Path must not be null");
            //对 path 进行修正,比如把 "\" 转为 "/"
            String pathToUse = StringUtils.cleanPath(path);
            if (pathToUse.startsWith("/")) {
                pathToUse = pathToUse.substring(1);
            }
            this.path = pathToUse;
         //获取当前线程的 ClassLoader
    this.classLoader = (classLoader != null ? classLoader : ClassUtils.getDefaultClassLoader()); }

    这句代码把配置文件封装为 ClassPathResource,以便于读取。

    接下来是  new XmlBeanFactory

    //根据提供的resource 加载 bean definition
    public XmlBeanFactory(Resource resource) throws BeansException {
            this(resource, null);
        }
    
    public XmlBeanFactory(Resource resource, BeanFactory parentBeanFactory) throws BeansException {
         //parentBeanFactory 初始值为空
    super(parentBeanFactory);  
         //这句才是重点,reader指的是
    XmlBeanDefinitionReader
         this.reader.loadBeanDefinitions(resource);
    }

     XmlBeanDefinitionReader 的 loadBeanDefinitions

    public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
         //把 Resource 转为 EncodedResource,用于对资源文件编码处理,当设置了编码属性,spring 会使用相应的编码作为输入流的编码。
    return loadBeanDefinitions(new EncodedResource(resource)); } public int loadBeanDefinitions(EncodedResource encodedResource) throws BeanDefinitionStoreException { 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 = new HashSet<>(4); this.resourcesCurrentlyBeingLoaded.set(currentResources); } if (!currentResources.add(encodedResource)) { throw new BeanDefinitionStoreException( "Detected cyclic loading of " + encodedResource + " - check your import definitions!"); } try { 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); } finally { currentResources.remove(encodedResource); if (currentResources.isEmpty()) { this.resourcesCurrentlyBeingLoaded.remove(); } } }
    doLoadBeanDefinitions,我删除了一些不重要的catch
    //
    protected
    int doLoadBeanDefinitions(InputSource inputSource, Resource resource) throws BeanDefinitionStoreException { try {
           //加载XML,获取对应的document Document doc
    = doLoadDocument(inputSource, resource); int count = registerBeanDefinitions(doc, resource); if (logger.isDebugEnabled()) { logger.debug("Loaded " + count + " bean definitions from " + resource); } return count; }catch (Throwable ex) { throw new BeanDefinitionStoreException(resource.getDescription(), "Unexpected exception parsing XML document from " + resource, ex); } }
    
    
    doLoadBeanDefinitions 比较重要的是这句代码
    int count = registerBeanDefinitions(doc, resource);

    真正的执行在这里DefaultBeanDefinitionDocumentReader 类中的doRegisterBeanDefinitions方法,这个方法的代码如下
    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);
                    // 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);
         //真正解析bean标签的地方 parseBeanDefinitions(root,
    this.delegate); postProcessXml(root); this.delegate = parent; } protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) { if (delegate.isDefaultNamespace(root)) { 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; if (delegate.isDefaultNamespace(ele)) {
                   //系统默认的bean标签 parseDefaultElement(ele, delegate); }
    else {
                   //自定义的 bean 标签 delegate.parseCustomElement(ele); } } } }
    else { delegate.parseCustomElement(root); } }

    这时候我们看到这里才是真正解析xml文件里bean标签的内容。

     
  • 相关阅读:
    HashMap源码分析jdk1.8
    Struts1.x总结
    session的使用
    浅谈EL
    浅谈JavaBean
    try、catch、finally带return的执行顺序总结
    jvm内存模型
    left join 、right join 、inner join之间的区别
    js按键事件
    log4j配置详解
  • 原文地址:https://www.cnblogs.com/fightingting/p/12616705.html
Copyright © 2011-2022 走看看