美文网首页
IOC容器初始化-二

IOC容器初始化-二

作者: liu_c02c | 来源:发表于2018-07-05 00:18 被阅读0次

    上一篇走了一遍源码,知道了IOC容器大概的一个初始化过程。

    spring ioc的一个过程是:

    1、定位

    ClassPathXmlApplicationContext的构造方法,输入资源路径,

    public ClassPathXmlApplicationContext(
                String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
          //关键代码
         /**
          * 设置资源路径
          */
         setConfigLocations(configLocations);
    }
    

    然后由AbstractBeanDefinitionReaderResourceLoader对configLocations进行转化为Resource

    public int loadBeanDefinitions(String location, @Nullable Set<Resource> actualResources) throws BeanDefinitionStoreException 
    

    2、加载

    跟踪代码到XmlBeanDefinitionReader,它的loadBeanDefinitions才是加载的真正入口

    public int loadBeanDefinitions(EncodedResource encodedResource)throws BeanDefinitionStoreException {
        //关键代码
        return doLoadBeanDefinitions(inputSource, encodedResource.getResource());
    }
    
    protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource){
        //关键代码
        Document doc = doLoadDocument(inputSource, resource);
        return registerBeanDefinitions(doc, resource);
    }
    

    2.1、加载Dom对象

    由DefaultDocumentLoader对Resource进行解析,生成Dom对象

    private DocumentLoader documentLoader = new DefaultDocumentLoader();
    protected Document doLoadDocument(InputSource inputSource, Resource resource) throws Exception {
       return this.documentLoader.loadDocument(inputSource, getEntityResolver(), this.errorHandler,
             getValidationModeForResource(resource), isNamespaceAware());
    }
    

    2.2、DefaultBeanDefinitionDocumentReader对dom对象进行更加深入的解析

    public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
       this.readerContext = readerContext;
       logger.debug("Loading bean definitions");
       Element root = doc.getDocumentElement();//获取element对象
       doRegisterBeanDefinitions(root);//根据element进行更加深入的解析
    }
    
    protected void doRegisterBeanDefinitions(Element root) {
       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;
             }
          }
       }
    
       preProcessXml(root);
       parseBeanDefinitions(root, this.delegate);
       postProcessXml(root);
    
       this.delegate = parent;
    }
    

    doRegisterBeanDefinitions,这个方法,做了一下几件事:

    a)生成BeanDefinitionParserDelegate,这个接口后续对Element进行bean的解析

    b) xml加载解析的前置操作

    c)委派BeanDefinitionParserDelegate进行解析任务

    d)xml加载解析的后置操作

    进到parseBeanDefinitions方法,对Element进行循环解析parseDefaultElement(假设是默认配置),

    private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
       if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
          importBeanDefinitionResource(ele);
       }
       else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
          processAliasRegistration(ele);
       }
       else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
          processBeanDefinition(ele, delegate);
       }
       else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
          // recurse
          doRegisterBeanDefinitions(ele);
       }
    }
    

    拿bean的解析来说,processBeanDefinition(ele, delegate)

    /**
     * Process the given bean element, parsing the bean definition
     * and registering it with the registry.
     */
    protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
       BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
       if (bdHolder != null) {
          bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
          try {
             // Register the final decorated instance.
             BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
          }
          catch (BeanDefinitionStoreException ex) {
             getReaderContext().error("Failed to register bean definition with name '" +
                   bdHolder.getBeanName() + "'", ele, ex);
          }
          // Send registration event.
          getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
       }
    }
    

    由上面的代码可以知道:

    a)由BeanDefinitionParserDelegate对element进行解析,生成BeanDefinitionHolder(它是对配置文件的描述,如beanname,class,id等等)

    b)由BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());进行注册,从而引申到注册

    3、注册

    BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());

    public static void registerBeanDefinition(
          BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
          throws BeanDefinitionStoreException {
    
       // Register bean definition under primary name.
       String beanName = definitionHolder.getBeanName();
       registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());//由BeanDefinitionRegistry维护BeanDefinition
    
       // Register aliases for bean name, if any.
       String[] aliases = definitionHolder.getAliases();
       if (aliases != null) {
          for (String alias : aliases) {
             registry.registerAlias(beanName, alias);
          }
       }
    }
    

    由上面的代码可以得知:BeanDefinition实际是由BeanDefinitionRegistry.registerBeanDefinition(委托给DefaultListableBeanFactory.registerBeanDefinition)进行注册的,从下面这个方法也可以得到验证:

    @Override
    public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
          throws BeanDefinitionStoreException {
    
      //关键代码
      this.beanDefinitionMap.put(beanName, beanDefinition);
    }
    

    由上面的代码可以知道,IOC注册最后由Map进行维护

    /** Map of bean definition objects, keyed by bean name */
    private final Map<String, BeanDefinition> beanDefinitionMap = new ConcurrentHashMap<>(256);
    

    相关文章

      网友评论

          本文标题:IOC容器初始化-二

          本文链接:https://www.haomeiwen.com/subject/aicuuftx.html