Spring源码阅读(一):IoC实现原理

IoC实现原理

IoC容器初始化过程

  • 定位:定位配置文件和扫描相关的注解;
  • 加载:将配置信息载入到内存中;
  • 注册:根据载入的信息,将对象初始化到IoC容器中。

spirng的入口是ApplicationContext,细分为ClassPathXmlApplicationContext、AnnotationConfigApplicationContext、WebApplicationContext等等几种不同的方式,用户使用哪种方式就会进入哪种ApplicationContext。BeanDefinition同样也分成如XmlBeanDefinition等等方式,BeanDefinitionReader也是同样的分为几种方式。

下面以ClassPathXmlApplicationContext为例:

ClassPathXmlApplicationContext的构造方法:

进入this:

/**
 * Create a new ClassPathXmlApplicationContext with the given parent,
 * loading the definitions from the given XML files.
 * @param configLocations array of resource locations
 * @param refresh whether to automatically refresh the context,
 * loading all bean definitions and creating all singletons.
 * Alternatively, call refresh manually after further configuring the context.
 * @param parent the parent context
 * @throws BeansException if context creation failed
 * @see #refresh()
 */
/**
 * 翻译一下注解的意思:
 * super一个父ApplicationContext(可以为空),来创建这个ClassPathXmlApplicationContext
 * 从xml文件中加载definitions(即setConfigLocations(configLocations)方法)
 * 加载所有的definitions,或者手动调用refresh()方法配置context
 */
public ClassPathXmlApplicationContext(
        String[] configLocations, boolean refresh, @Nullable ApplicationContext parent)
        throws BeansException {

    super(parent);
    setConfigLocations(configLocations);
    if (refresh) {
        refresh();
    }
}

这个方法调用了AbstractRefreshableConfigApplicationContextsetConfigLocations(configLocations)方法来定位definitions,并将结果保存在AbstractRefreshableConfigApplicationContextconfigLocations数组中(这个数组在后面的使用reader解析bean资源的时候会用到):

/**
 * Set the config locations for this application context.
 * 

If not set, the implementation may use a default as appropriate. */ /** * 解析资源文件路径 * locations表示多个资源文件路径的字符串数组 * 将locations字符串数组解析为configLocations路径数组的方法 */ public void setConfigLocations(@Nullable String... locations) { if (locations != null) { Assert.noNullElements(locations, ""Config locations must not be null""); this.configLocations = new String[locations.length]; for (int i = 0; i < locations.length; i++) { // resolvePath方法:将字符串解析为路径的方法 // 路径保存至configLocations数组中 this.configLocations[i] = resolvePath(locations[i]).trim(); } } else { this.configLocations = null; } }

接下来,根据这个构造方法的传参可知boolean refresh的值为true,所以会进入AbstractApplicationContextrefresh()方法:

@Override
public void refresh() throws BeansException, IllegalStateException {
    synchronized (this.startupShutdownMonitor) {
        // Prepare this context for refreshing.
        //1、调用容器准备刷新的方法,获取容器的当时时间,同时给容器设置同步标识
        prepareRefresh();

        // Tell the subclass to refresh the internal bean factory.
        //2、告诉子类启动refreshBeanFactory()方法来刷新内部的bean factory。
        // Bean定义资源文件的载入从子类的refreshBeanFactory()方法启动
        ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();

        // Prepare the bean factory for use in this context.
        //3、为BeanFactory配置容器特性,例如类加载器、事件处理器等
        prepareBeanFactory(beanFactory);

        try {
            // Allows post-processing of the bean factory in context subclasses.
            //4、为容器的某些子类指定特殊的BeanPost事件处理器
            postProcessBeanFactory(beanFactory);

            // Invoke factory processors registered as beans in the context.
            //5、调用所有注册的BeanFactoryPostProcessor的Bean
            invokeBeanFactoryPostProcessors(beanFactory);

            // Register bean processors that intercept bean creation.
            //6、为BeanFactory注册BeanPost事件处理器.
            //BeanPostProcessor是Bean后置处理器,用于监听容器触发的事件
            registerBeanPostProcessors(beanFactory);

            // Initialize message source for this context.
            //7、初始化信息源,和国际化相关.
            initMessageSource();

            // Initialize event multicaster for this context.
            //8、初始化容器事件传播器.
            initApplicationEventMulticaster();

            // Initialize other special beans in specific context subclasses.
            //9、调用子类的某些特殊Bean初始化方法
            onRefresh();

            // Check for listener beans and register them.
            //10、为事件传播器注册事件监听器.
            registerListeners();

            // Instantiate all remaining (non-lazy-init) singletons.
            //11、初始化所有剩余的单例Bean
            finishBeanFactoryInitialization(beanFactory);

            // Last step: publish corresponding event.
            //12、初始化容器的生命周期事件处理器,并发布容器的生命周期事件
            finishRefresh();
        }

        catch (BeansException ex) {
            if (logger.isWarnEnabled()) {
                logger.warn(""Exception encountered during context initialization - "" +
                        ""cancelling refresh attempt: "" + ex);
            }

            // Destroy already created singletons to avoid dangling resources.
            //13、销毁已创建的Bean
            destroyBeans();

            // Reset 'active' flag.
            //14、取消refresh操作,重置容器的同步标识。
            cancelRefresh(ex);

            // Propagate exception to caller.
            throw ex;
        }

        finally {
            // Reset common introspection caches in Spring's core, since we
            // might not ever need metadata for singleton beans anymore...
            //15、重设公共缓存
            resetCommonCaches();
        }
    }
}

refresh()方法通过obtainFreshBeanFactory()方法来载入beanFactory,并对context进行一系列初始化。

进入obtainFreshBeanFactory()方法:

/**
 * Tell the subclass to refresh the internal bean factory.
 */
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
    //委派模式,委派至AbstractRefreshableApplicationContext的refreshBeanFactory方法
    refreshBeanFactory();
    ConfigurableListableBeanFactory beanFactory = getBeanFactory();
    if (logger.isDebugEnabled()) {
        logger.debug(""Bean factory for "" + getDisplayName() + "": "" + beanFactory);
    }
    return beanFactory;
}

进入AbstractRefreshableApplicationContextrefreshBeanFactory()方法:

/**
 * This implementation performs an actual refresh of this context's underlying
 * bean factory, shutting down the previous bean factory (if any) and
 * initializing a fresh bean factory for the next phase of the context's lifecycle.
 */
/**
 * 注释翻译:
 * 这个实现重新刷新了这个context的实际的bean factory
 * 销毁之前的bean,关闭bean factory
 * 并为context的下一个生命周期初始化了一个新的bean factory
 */
@Override
protected final void refreshBeanFactory() throws BeansException {
    //如果已经有容器,销毁容器中的bean,关闭容器
    if (hasBeanFactory()) {
        destroyBeans();
        closeBeanFactory();
    }
    try {
        //创建IOC容器beanFactory
        DefaultListableBeanFactory beanFactory = createBeanFactory();
        beanFactory.setSerializationId(getId());
        //对IOC容器进行定制化,如设置启动参数,开启注解的自动装配等
        customizeBeanFactory(beanFactory);
        //调用载入Bean定义的方法
        loadBeanDefinitions(beanFactory);
        synchronized (this.beanFactoryMonitor) {
            this.beanFactory = beanFactory;
        }
    }
    catch (IOException ex) {
        throw new ApplicationContextException(""I/O error parsing bean definition source for "" + getDisplayName(), ex);
    }
}

在这个refreshBeanFactory()方法中,创建了DefaultListableBeanFactory类的对象beanFactory,这就是我们的IoC容器,所以注意了,我们最终得到的beanFactory是一个DefaultListableBeanFactory

又通过调用AbstractXmlApplicationContextloadBeanDefinitions(beanFactory)来将Bean载入beanFactory

/**
 * Loads the bean definitions via an XmlBeanDefinitionReader.
 * @see org.springframework.beans.factory.xml.XmlBeanDefinitionReader
 * @see #initBeanDefinitionReader
 * @see #loadBeanDefinitions
 */
/**
 * 注释翻译:
 * 通过XmlBeanDefinitionReader来载入bean definitions
 */
@Override
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
    // Create a new XmlBeanDefinitionReader for the given BeanFactory.
    // 创建XmlBeanDefinitionReader,即Bean读取器,并通过回调设置到容器beanFactory中
    XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);

    // Configure the bean definition reader with this context's
    // resource loading environment.
    //为Bean读取器设置Spring资源加载器,容器beanFactory本身也是一个资源加载器
    beanDefinitionReader.setEnvironment(this.getEnvironment());
    beanDefinitionReader.setResourceLoader(this);
    //为Bean读取器设置SAX xml解析器
    beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));

    // Allow a subclass to provide custom initialization of the reader,
    // then proceed with actually loading the bean definitions.
    //当Bean读取器读取Bean定义的Xml资源文件时,启用Xml的校验机制
    initBeanDefinitionReader(beanDefinitionReader);
    //Bean读取器真正实现加载的方法
    loadBeanDefinitions(beanDefinitionReader);
}

此时,创建的XmlBeanDefinitionReader是一个bean阅读器beanDefinitionReader,这个阅读器有beanFactory属性,通过它读取到的bean信息会回调至beanFactory中。

这个方法中,只有最后一句的loadBeanDefinitions(beanDefinitionReader)方法才是真正的加载bean的方法,进入这个方法:

/**
 * Load the bean definitions with the given XmlBeanDefinitionReader.
 * 

The lifecycle of the bean factory is handled by the {@link #refreshBeanFactory} * method; hence this method is just supposed to load and/or register bean definitions. */ //Xml Bean读取器加载Bean定义资源 protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException { //获取Bean定义资源的定位 Resource[] configResources = getConfigResources(); if (configResources != null) { //Xml Bean读取器调用其父类AbstractBeanDefinitionReader读取定位的Bean定义资源 reader.loadBeanDefinitions(configResources); } //如果Bean定义资源定位为空,则获取FileSystemXmlApplicationContext构造方法中setConfigLocations方法设置的资源 String[] configLocations = getConfigLocations(); if (configLocations != null) { //Xml Bean读取器调用其父类AbstractBeanDefinitionReader读取定位的Bean定义资源 reader.loadBeanDefinitions(configLocations); } }

Resource[] configResources = getConfigResources();

方法中的这句话,获取到的是之前我们在ClassPathXmlApplicationContext的构造方法中,setConfigLocations(configLocations)方法里保存的Resource[]数组configResources。

可以看到不管configResources是否为空,最后调用的都是reader的loadBeanDefinitions()方法(重载,虽然入参一个是Resource一个是String,但最终得到的都是Resource)。

先进入第一个的loadBeanDefinitions(configResources),这里会进入AbstractBeanDefinitionReader类,也就是reader的类:

@Override
public int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException {
    Assert.notNull(resources, ""Resource array must not be null"");
    int counter = 0;
    for (Resource resource : resources) {
        counter += loadBeanDefinitions(resource);
    }
    return counter;
}

因为这里是加载xml文件资源,所以我们进入XmlBeanDefinitionReaderloadBeanDefinitions(resource)方法(策略模式:这里会有多个类的loadBeanDefinitions方法可以进入),这个方法的具体实现:

//XmlBeanDefinitionReader加载资源的入口方法
@Override
public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
    //将读入的XML资源进行特殊编码处理
    return loadBeanDefinitions(new EncodedResource(resource));
}

进入这个XmlBeanDefinitionReader的loadBeanDefinitions()方法:

/**
 * Load bean definitions from the specified XML file.
 * @param encodedResource the resource descriptor for the XML file,
 * allowing to specify an encoding to use for parsing the file
 * @return the number of bean definitions found
 * @throws BeanDefinitionStoreException in case of loading or parsing errors
 */
/**
 * 载入XML形式Bean定义资源文件方法
 * 参数:xml文件的编码资源
 * 返回:找到的bean definitions的数量
 */
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());
   }

   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的IO流
      InputStream inputStream = encodedResource.getResource().getInputStream();
      try {
         //从InputStream中得到XML的解析源
         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();
      }
   }
}

这个方法主要目的就是将xml资源转为InputStream流读取,由inputStream得到xml的解析源inputSource,通过doLoadBeanDefinitions()来读取资源信息。

我们进入doLoadBeanDefinitions()看一下:

/**
 * Actually load bean definitions from the specified XML file.
 * @param inputSource the SAX InputSource to read from
 * @param resource the resource descriptor for the XML file
 * @return the number of bean definitions found
 * @throws BeanDefinitionStoreException in case of loading or parsing errors
 * @see #doLoadDocument
 * @see #registerBeanDefinitions
 */
//从特定XML文件中实际载入Bean定义资源的方法
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
      throws BeanDefinitionStoreException {
   try {
      //将XML文件转换为DOM对象,解析过程由documentLoader实现
      Document doc = doLoadDocument(inputSource, resource);
      //这里是启动对Bean定义解析的详细过程,该解析过程会用到Spring的Bean配置规则
      return registerBeanDefinitions(doc, resource);
   }
   catch (BeanDefinitionStoreException ex) {
      throw ex;
   }
   catch (SAXParseException ex) {
      throw new XmlBeanDefinitionStoreException(resource.getDescription(),
            ""Line "" + ex.getLineNumber() + "" in XML document from "" + resource + "" is invalid"", ex);
   }
   catch (SAXException ex) {
      throw new XmlBeanDefinitionStoreException(resource.getDescription(),
            ""XML document from "" + resource + "" is invalid"", ex);
   }
   catch (ParserConfigurationException ex) {
      throw new BeanDefinitionStoreException(resource.getDescription(),
            ""Parser configuration exception parsing XML from "" + resource, ex);
   }
   catch (IOException ex) {
      throw new BeanDefinitionStoreException(resource.getDescription(),
            ""IOException parsing XML document from "" + resource, ex);
   }
   catch (Throwable ex) {
      throw new BeanDefinitionStoreException(resource.getDescription(),
            ""Unexpected exception parsing XML document from "" + resource, ex);
   }
}

这个方法主要是用documentLoader()方法将XML文件转换为DOM对象,并通过调用registerBeanDefinitions()方法来启动对Bean解析。

这里又创建了一个阅读器BeanDefinitionDocumentReader,主要是对DOM对象的阅读

registerBeanDefinitions()方法是对bean的解析注册:

//按照Spring的Bean语义要求将Bean定义资源解析并转换为容器内部数据结构
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
   //得到BeanDefinitionDocumentReader来对xml格式的BeanDefinition解析
   BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
   //获得容器中注册的Bean数量
   int countBefore = getRegistry().getBeanDefinitionCount();
   //解析过程入口,委派模式,实际是在DefaultBeanDefinitionDocumentReader完成注册
   documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
   //统计解析的Bean数量
   return getRegistry().getBeanDefinitionCount() - countBefore;
}

进入的是BeanDefinitionDocumentReaderregisterBeanDefinitions()方法,委派至DefaultBeanDefinitionDocumentReaderregisterBeanDefinitions()

//根据Spring DTD对Bean的定义规则解析Bean定义Document对象
@Override
public void  registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
   //获得XML描述符
   this.readerContext = readerContext;
   logger.debug(""Loading bean definitions"");
   //获得Document的根元素
   Element root = doc.getDocumentElement();
   doRegisterBeanDefinitions(root);
}

这里创建了Document的根元素root,注册的也是根元素roo。

进入doRegisterBeanDefinitions()方法(属于DefaultBeanDefinitionDocumentReader类):

/**
 * Register each bean definition within the given root {@code <beans/>} element.
 */
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.

   //具体的解析过程由BeanDefinitionParserDelegate实现,
   //BeanDefinitionParserDelegate中定义了Spring Bean定义XML文件的各种元素
   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);
   //从Document的根元素开始进行Bean定义的Document对象
   parseBeanDefinitions(root, this.delegate);
   //在解析Bean定义之后,进行自定义的解析,增加解析过程的可扩展性
   postProcessXml(root);

   this.delegate = parent;
}

这个对DefaultBeanDefinitionDocumentReader的属性delegate进行了赋值,即createDelegate(getReaderContext(), root, parent)操作,使delegate获取到了根元素root的各种属性。这里的代码会保存每一代的root信息。(难点,待续...)

进入parseBeanDefinitions(root, this.delegate)方法(属于DefaultBeanDefinitionDocumentReader类):

//使用Spring的Bean规则从Document的根元素开始进行Bean定义的Document对象
protected void parseBeanDefinitions(Element root, BeanDefinitionParserDelegate delegate) {
   //Bean定义的Document对象使用了Spring默认的XML命名空间
   if (delegate.isDefaultNamespace(root)) {
      //获取Bean定义的Document对象根元素的所有子节点
      NodeList nl = root.getChildNodes();
      for (int i = 0; i < nl.getLength(); i++) {
         Node node = nl.item(i);
         //获得Document节点是XML元素节点
         if (node instanceof Element) {
            Element ele = (Element) node;
            //Bean定义的Document的元素节点使用的是Spring默认的XML命名空间
            if (delegate.isDefaultNamespace(ele)) {
               //使用Spring的Bean规则解析元素节点
               parseDefaultElement(ele, delegate);
            }
            else {
               //没有使用Spring默认的XML命名空间,则使用用户自定义的解//析规则解析元素节点
               delegate.parseCustomElement(ele);
            }
         }
      }
   }
   else {
      //Document的根节点没有使用Spring默认的命名空间,则使用用户自定义的
      //解析规则解析Document根节点
      delegate.parseCustomElement(root);
   }
}

此时我们只看Spring默认的XML命名空间存在的Document对象。默认BeanDefinitionParserDelegate会处理 http://www.springframework.org/schema/beans 命名空间下元素及其属性,使用的是parseDefaultElement(ele, delegate)方法。

进入parseDefaultElement(ele, delegate)

//解析Bean定义资源Document对象的普通元素
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
   BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
   // BeanDefinitionHolder是对BeanDefinition的封装,即Bean定义的封装类
   //对Document对象中<Bean>元素的解析由BeanDefinitionParserDelegate实现
   // BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
   if (bdHolder != null) {
      bdHolder = delegate.decorateBeanDefinitionIfRequired(ele, bdHolder);
      try {
         // Register the final decorated instance.
         //向Spring IOC容器注册解析得到的Bean定义,这是Bean定义向IOC容器注册的入口
         BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry());
      }
      catch (BeanDefinitionStoreException ex) {
         getReaderContext().error(""Failed to register bean definition with name '"" +
               bdHolder.getBeanName() + ""'"", ele, ex);
      }
      // Send registration event.
      //在完成向Spring IOC容器注册解析得到的Bean定义之后,发送注册事件
      getReaderContext().fireComponentRegistered(new BeanComponentDefinition(bdHolder));
   }
}

在这个方法里,bdHolder是对Document对象的Element的封装。

而在delegate.parseBeanDefinitionElement(ele)方法中,是对Element的解析,获取到Element的id、name、alias各种属性值,将id赋给beanName,如果Element中没有配置id属性时,将别名中的第一个值赋值给beanName。并使用parseBeanDefinitionElement()方法将element封装成为AbstractBeanDefinition对象。最后封装成BeanDefinitionHolder对象bdHolder并返回。

得到bdHolder后,再调用BeanDefinitionReaderUtils.registerBeanDefinition(bdHolder, getReaderContext().getRegistry())方法,注册BeanDefinition。此时来到了BeanDefinitionReaderUtils中:

public static void registerBeanDefinition(
      BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
      throws BeanDefinitionStoreException {

   // Register bean definition under primary name.
   //获取解析的BeanDefinition的名称
   String beanName = definitionHolder.getBeanName();
   //向IOC容器注册BeanDefinition
   registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());

   // Register aliases for bean name, if any.
   //如果解析的BeanDefinition有别名,向容器为其注册别名
   String[] aliases = definitionHolder.getAliases();
   if (aliases != null) {
      for (String alias : aliases) {
         registry.registerAlias(beanName, alias);
      }
   }
}

直接看registry.registerBeanDefinition()方法,进入的是DefaultListableBeanFactory类,这是最终我们生成IoC容器即 beanDefinitionMap的地方:

//向IOC容器注册解析的BeanDefiniton
@Override
public void registerBeanDefinition(String beanName, BeanDefinition beanDefinition)
      throws BeanDefinitionStoreException {

   Assert.hasText(beanName, ""Bean name must not be empty"");
   Assert.notNull(beanDefinition, ""BeanDefinition must not be null"");

   //校验解析的BeanDefiniton
   if (beanDefinition instanceof AbstractBeanDefinition) {
      try {
         ((AbstractBeanDefinition) beanDefinition).validate();
      }
      catch (BeanDefinitionValidationException ex) {
         throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
               ""Validation of bean definition failed"", ex);
      }
   }

   BeanDefinition oldBeanDefinition;

   oldBeanDefinition = this.beanDefinitionMap.get(beanName);

   if (oldBeanDefinition != null) {
      if (!isAllowBeanDefinitionOverriding()) {
         throw new BeanDefinitionStoreException(beanDefinition.getResourceDescription(), beanName,
               ""Cannot register bean definition ["" + beanDefinition + ""] for bean '"" + beanName +
               ""': There is already ["" + oldBeanDefinition + ""] bound."");
      }
      else if (oldBeanDefinition.getRole() < beanDefinition.getRole()) {
         // e.g. was ROLE_APPLICATION, now overriding with ROLE_SUPPORT or ROLE_INFRASTRUCTURE
         if (this.logger.isWarnEnabled()) {
            this.logger.warn(""Overriding user-defined bean definition for bean '"" + beanName +
                  ""' with a framework-generated bean definition: replacing ["" +
                  oldBeanDefinition + ""] with ["" + beanDefinition + ""]"");
         }
      }
      else if (!beanDefinition.equals(oldBeanDefinition)) {
         if (this.logger.isInfoEnabled()) {
            this.logger.info(""Overriding bean definition for bean '"" + beanName +
                  ""' with a different definition: replacing ["" + oldBeanDefinition +
                  ""] with ["" + beanDefinition + ""]"");
         }
      }
      else {
         if (this.logger.isDebugEnabled()) {
            this.logger.debug(""Overriding bean definition for bean '"" + beanName +
                  ""' with an equivalent definition: replacing ["" + oldBeanDefinition +
                  ""] with ["" + beanDefinition + ""]"");
         }
      }
      this.beanDefinitionMap.put(beanName, beanDefinition);
   }
   else {
      if (hasBeanCreationStarted()) {
         // Cannot modify startup-time collection elements anymore (for stable iteration)
         //注册的过程中需要线程同步,以保证数据的一致性
         synchronized (this.beanDefinitionMap) {
            this.beanDefinitionMap.put(beanName, beanDefinition);
            List<String> updatedDefinitions = new ArrayList<>(this.beanDefinitionNames.size() + 1);
            updatedDefinitions.addAll(this.beanDefinitionNames);
            updatedDefinitions.add(beanName);
            this.beanDefinitionNames = updatedDefinitions;
            if (this.manualSingletonNames.contains(beanName)) {
               Set<String> updatedSingletons = new LinkedHashSet<>(this.manualSingletonNames);
               updatedSingletons.remove(beanName);
               this.manualSingletonNames = updatedSingletons;
            }
         }
      }
      else {
         // Still in startup registration phase
         this.beanDefinitionMap.put(beanName, beanDefinition);
         this.beanDefinitionNames.add(beanName);
         this.manualSingletonNames.remove(beanName);
      }
      this.frozenBeanDefinitionNames = null;
   }

   //检查是否有同名的BeanDefinition已经在IOC容器中注册
   if (oldBeanDefinition != null || containsSingleton(beanName)) {
      //重置所有已经注册过的BeanDefinition的缓存
      resetBeanDefinition(beanName);
   }
}

方法里有this.beanDefinitionMap.put(beanName, beanDefinition),即表示将beanName和beanDefinition放入了这个IoC容器beanDefinitionMap中。此时,IoC的流程结束。

整个流程其实就是:定位到bean,加载、封装后,注册到IoC容器beanDefinitionMap中。通过类图我们来整理一下。

这是DefaultListableBeanFactory的类图:

这是ClassPathXmlApplicationContext的类图:

文章已创建 17

相关文章

开始在上面输入您的搜索词,然后按回车进行搜索。按ESC取消。

返回顶部