Spring Ioc: refresh响蓉、prepareRefresh烁设、obtainFreshBeanFactory 方法分析

前言

在文章 ApplicationContext 體系結(jié)構(gòu) 中我們從一張 ApplicationContext 體系的類圖開始,介紹了 ApplicationContext 體系中各個類的繼承關(guān)系撬腾,接著分析了 ClassPathXmlApplicationContext 和 AnnotationConfigApplicationContext 類的構(gòu)造函數(shù)中前兩個函數(shù)的源碼螟蝙。從本篇文章開始,將重點介紹 refresh 函數(shù)民傻。

  • AbstractApplicationContext::refresh
    ClassPathXmlApplicationContext 和 AnnotationConfigApplicationContext 類均繼承了 AbstractApplicationContext 類胰默,refresh 方法在該類中實現(xiàn)。

    public void refresh() throws BeansException, IllegalStateException {
        synchronized (this.startupShutdownMonitor) {
            // Prepare this context for refreshing.
            // 刷新預(yù)處理
            prepareRefresh();
    
            // Tell the subclass to refresh the internal bean factory.
            // (1) 創(chuàng)建 IOC 容器(DefaultListableBeanFactory)
            // (2) 加載 xml 文件(最終生成 Document 對象)
            // (3) 讀取 Document 對象漓踢,完成 BeanDefinition 的加載和注冊
            ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
    
            // Prepare the bean factory for use in this context.
            // 對IOC容器進(jìn)行預(yù)處理
            prepareBeanFactory(beanFactory);
    
            try {
                // Allows post-processing of the bean factory in context subclasses.
                postProcessBeanFactory(beanFactory);
    
                // Invoke factory processors registered as beans in the context.
                // 調(diào)用BeanFactoryPostProcessor后置處理器對 BeanDefinition 處理
                invokeBeanFactoryPostProcessors(beanFactory);
    
                // Register bean processors that intercept bean creation.
                // 注冊BeanPostProcessor后置處理器
                registerBeanPostProcessors(beanFactory);
    
                // Initialize message source for this context.
                // STEP 7: 初始化一些消息源(比如處理國際化的i18n等消息源)
                initMessageSource();
    
                // Initialize event multicaster for this context.
                // STEP 8: 初始化應(yīng)用事件廣播器
                initApplicationEventMulticaster();
    
                // Initialize other special beans in specific context subclasses.
                // STEP 9: 初始化一些特殊的bean
                onRefresh();
    
                // Check for listener beans and register them.
                // STEP 10: 注冊一些監(jiān)聽器
                registerListeners();
    
                // Instantiate all remaining (non-lazy-init) singletons.
                // STEP 11: 實例化剩余的單例bean(非懶加載方式)
                // 注意事項:Bean的IoC牵署、DI和AOP都是發(fā)生在此步驟
                finishBeanFactoryInitialization(beanFactory);
    
                // Last step: publish corresponding event.
                // STEP 12: 完成刷新時,需要發(fā)布對應(yīng)的事件
                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.
                destroyBeans();
                // Reset 'active' flag.
                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...
                resetCommonCaches();
            }
        }
    }
    
  • AbstractApplicationContext::prepareRefresh

    protected void prepareRefresh() {
        // Switch to active.
        // 記錄啟動時間喧半,容器狀態(tài)
        this.startupDate = System.currentTimeMillis();
        this.closed.set(false);
        this.active.set(true);
    
        if (logger.isInfoEnabled()) {
            logger.info("Refreshing " + this);
        }
    
        // Initialize any placeholder property sources in the context environment.
        // 空函數(shù)什么也沒做奴迅,初始化屬性配置在其子類中有實現(xiàn)(例如:AbstractRefreshableWebApplicationContext、GenericWebApplicationContext等)
        initPropertySources();
    
        // Validate that all properties marked as required are resolvable:
        // see ConfigurablePropertyResolver#setRequiredProperties
        /**
        * 1. 獲取 ConfigurableEnvironment
        * 2. 確保配置所有必須的屬性
        **/
        getEnvironment().validateRequiredProperties();
    
        // Store pre-refresh ApplicationListeners...
        // 創(chuàng)建早期時間監(jiān)聽器容集合挺据,保存早期監(jiān)聽器取具,也就是在之前已經(jīng)初始化的監(jiān)聽器脖隶。
        if (this.earlyApplicationListeners == null) {
            this.earlyApplicationListeners = new LinkedHashSet<>(this.applicationListeners);
        }
        else {
            // Reset local application listeners to pre-refresh state.
            this.applicationListeners.clear();
            this.applicationListeners.addAll(this.earlyApplicationListeners);
        }
    
        // Allow for the collection of early ApplicationEvents,
        // to be published once the multicaster is available...
        // 創(chuàng)建早期事件集合
        this.earlyApplicationEvents = new LinkedHashSet<>();
    }
    
  • ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory()

    創(chuàng)建 BeanFactory

    protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
        // 1.
        refreshBeanFactory();
        ConfigurableListableBeanFactory beanFactory = getBeanFactory();
        if (logger.isDebugEnabled()) {
            logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
        }
        return beanFactory;
    }
    
    • refreshBeanFactory
      AbstractApplicationContext 中該方法為空,在子類 AbstractRefreshableApplicationContext(ClassPathXmlApplicationContext繼承該類)者填、GenericApplicationContext(AnnotationConfigApplicationContext繼承該類)中對該方法進(jìn)行了擴展浩村。

      1. AbstractRefreshableApplicationContext::refreshBeanFactory

        protected final void refreshBeanFactory() throws BeansException {
            // 若已存在 BeanFactory,則銷毀容器中的 Bean 實例占哟,將 BeanFactory 置為 null
            if (hasBeanFactory()) {
                destroyBeans();
                closeBeanFactory();
            }
            try {
                // 創(chuàng)建 BeanFactory 實例心墅,類型為:DefaultListableBeanFactory
                DefaultListableBeanFactory beanFactory = createBeanFactory();
                beanFactory.setSerializationId(getId());
                // 定制beanFactory,設(shè)置相關(guān)屬性榨乎,包括是否允許覆蓋同名稱的不同定義的對象以及循環(huán)依賴
                // 可在子類中去擴展定義屬性:allowBeanDefinitionOverriding, allowCircularReferences
                customizeBeanFactory(beanFactory);
                // 加載 BeanDefinition怎燥,并注冊到IoC容器中(重點)
                loadBeanDefinitions(beanFactory);
                synchronized (this.beanFactoryMonitor) {
                    this.beanFactory = beanFactory;
                }
            }
            catch (IOException ex) {
                throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
            }
        }
        
        • loadBeanDefinitions
          在 AbstractRefreshableApplicationContext::refreshBeanFactory 中 loadBeanDefinitions 為重點代碼,接下來將詳細(xì)介紹改部分的代碼蜜暑。
          |-- AbstractRefreshableApplicationContext::refreshBeanFactory 
          |-- AbstractXmlApplicationContext::loadBeanDefinitions:走了多個重載方法 
              |--AbstractBeanDefinitionReader::loadBeanDefinitions:走了多個重載方法 
              |--XmlBeanDefinitionReader::loadBeanDefinitions:走了多個重載方法 
              |--XmlBeanDefinitionReader::doLoadBeanDefinitions 
              |--XmlBeanDefinitionReader::registerBeanDefinitions 
                      |-- DefaultBeanDefinitionDocumentReader
                          ::registerBeanDefinitions   
                          ::doRegisterBeanDefinitions 
                          ::parseBeanDefinitions 
                          ::parseDefaultElement 
                          ::processBeanDefinition 
                              |--BeanDefinitionParserDelegate
                              ::parseBeanDefinitionElement 
                              ::parseBeanDefinitionElement
          1. AbstractRefreshableApplicationContext:主要用來對BeanFactory提供 refresh 功能铐姚。包括BeanFactory的創(chuàng)建和 BeanDefinition 的定義、解析肛捍、注冊操作隐绵。
          2. AbstractXmlApplicationContext:提供對 xml 資源的解析功能,包括從Resource資源對象和資源路徑中加載XML文件拙毫。
          3. AbstractBeanDefinitionReader:主要提供對于 BeanDefinition 對象的讀取功能依许。具體讀取工作交給子類實現(xiàn)。
          4. XmlBeanDefinitionReader:主要通過 DOM4J 對于 XML資源 的讀取缀蹄、解析功能峭跳,并提供對于 BeanDefinition 的注冊功能。
          5. DefaultBeanDefinitionDocumentReader
          6. BeanDefinitionParserDelegate
          
          • AbstractXmlApplicationContext::loadBeanDefinitions
          protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
              // Create a new XmlBeanDefinitionReader for the given BeanFactory.
              // 創(chuàng)建 XmlBeanDefinitionReader缺前, 此時會初始化 ResourceLoaderLoader
              XmlBeanDefinitionReader beanDefinitionReader = new XmlBeanDefinitionReader(beanFactory);
          
              // Configure the bean definition reader with this context's
              // resource loading environment.
              beanDefinitionReader.setEnvironment(this.getEnvironment());
              beanDefinitionReader.setResourceLoader(this);
              beanDefinitionReader.setEntityResolver(new ResourceEntityResolver(this));
          
              // Allow a subclass to provide custom initialization of the reader,
              // then proceed with actually loading the bean definitions.
              initBeanDefinitionReader(beanDefinitionReader);
              loadBeanDefinitions(beanDefinitionReader);
          }
          
          protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
              // debug 中 configResourses 為 null
              Resource[] configResources = getConfigResources();
              if (configResources != null) {
                  reader.loadBeanDefinitions(configResources);
              }
              String[] configLocations = getConfigLocations();
              if (configLocations != null) {
                  // 根據(jù)配置文件位置加載BeanDefinition
                  reader.loadBeanDefinitions(configLocations);
              }
          }
          
          // AbstractBeanDefinitionReader::loadBeanDefinitions
          public int loadBeanDefinitions(String... locations) throws BeanDefinitionStoreException {
              Assert.notNull(locations, "Location array must not be null");
              int counter = 0;
              for (String location : locations) {
                  counter += loadBeanDefinitions(location);
              }
              return counter;
          }
          
          public int loadBeanDefinitions(String location, @Nullable Set<Resource> actualResources) throws BeanDefinitionStoreException {
              // 初始化 XmlBeanDefinitionReader 時已經(jīng)初始化了 ResourceLoader
              // XmlBeanDefinitionReader 無法直接加載配置文件蛀醉,因此需要委托 ResourceLoader 將配置文件加載為 Resource 對象
              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);
                      // 根據(jù) Resource 加載 BeanDefinition
                      int loadCount = loadBeanDefinitions(resources);
                      if (actualResources != null) {
                          for (Resource resource : resources) {
                              actualResources.add(resource);
                          }
                      }
                      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 {
                  // Can only load single resources by absolute URL.
                  Resource resource = resourceLoader.getResource(location);
                  int loadCount = loadBeanDefinitions(resource);
                  if (actualResources != null) {
                      actualResources.add(resource);
                  }
                  if (logger.isDebugEnabled()) {
                      logger.debug("Loaded " + loadCount + " bean definitions from location [" + location + "]");
                  }
                  return loadCount;
              }
          }
          
          • XmlBeanDefinitionReader::loadBeanDefinitions
          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);
              }
          
              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();
                  }
              }
          }
          
          protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
                  throws BeanDefinitionStoreException {
              try {
                  // 將配置文件轉(zhuǎn)換為 Document 對象
                  Document doc = doLoadDocument(inputSource, resource);
                  return registerBeanDefinitions(doc, resource);
              }
              // .. 此處異常捕獲處理代碼省去
          }
          
          public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
              // 創(chuàng)建 DefaultBeanDefinitionDocumentReader 對象
              BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
              int countBefore = getRegistry().getBeanDefinitionCount();
              // 1. 創(chuàng)建 Reader 上下文
              // 2. 根據(jù) Document 對象加載 BeanDefinition
              documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
              return getRegistry().getBeanDefinitionCount() - countBefore;
          }
          
          • XmlBeanDefinitionReader::registerBeanDefinitions
          // 創(chuàng)建 XmlReaderContext, 需要創(chuàng)建 NameSpaceHandlerResolver 用來處理 xml 配置文件中的各命名空間
          // 讀取 "META-INF/spring.handlers" 創(chuàng)建 DefaultNamespaceHandlerResolver
          public XmlReaderContext createReaderContext(Resource resource) {
              return new XmlReaderContext(resource, this.problemReporter, this.eventListener,
                      this.sourceExtractor, this, getNamespaceHandlerResolver());
          }
          
          public NamespaceHandlerResolver getNamespaceHandlerResolver() {
              if (this.namespaceHandlerResolver == null) {
                  this.namespaceHandlerResolver = createDefaultNamespaceHandlerResolver();
              }
              return this.namespaceHandlerResolver;
          }
          
          protected NamespaceHandlerResolver createDefaultNamespaceHandlerResolver() {
              ClassLoader cl = (getResourceLoader() != null ? getResourceLoader().getClassLoader() : getBeanClassLoader());
              return new DefaultNamespaceHandlerResolver(cl);
          }
          
          public DefaultNamespaceHandlerResolver(@Nullable ClassLoader classLoader) {
              //public static final String DEFAULT_HANDLER_MAPPINGS_LOCATION = "META-INF/spring.handlers";
              this(classLoader, DEFAULT_HANDLER_MAPPINGS_LOCATION);
          }
          
          • DefaultBeanDefinitionDocumentReader::registerBeanDefinitions
          public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
              this.readerContext = readerContext;
              logger.debug("Loading bean definitions");
              Element root = doc.getDocumentElement();
              doRegisterBeanDefinitions(root);
          }
          
          protected void doRegisterBeanDefinitions(Element root) {
              
              BeanDefinitionParserDelegate parent = this.delegate;
              // 根據(jù) Reader 上下文創(chuàng)建 BeanDefinitionParserDelegate
              this.delegate = createDelegate(getReaderContext(), root, parent);
              /**
              * BeanDefinitionParserDelegate delegate = new BeanDefinitionParserDelegate(readerContext);
              * delegate.initDefaults(root, parentDelegate);
              **/
          
              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;
                      }
                  }
              }
              // 空函數(shù)
              preProcessXml(root);
              // 解析標(biāo)簽
              parseBeanDefinitions(root, this.delegate);
              // 空函數(shù)
              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)) {
                              // 處理默認(rèn)的標(biāo)簽元素:bean/import/alias/beans
                              parseDefaultElement(ele, delegate);
                          }
                          else {
                              // 處理自定義的標(biāo)簽
                              delegate.parseCustomElement(ele);
                          }
                      }
                  }
              }
              else {
                  delegate.parseCustomElement(root);
              }
          }
          
          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)) {
                  // 處理 bean 標(biāo)簽
                  processBeanDefinition(ele, delegate);
              }
              else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
                  // recurse 遞歸調(diào)用
                  doRegisterBeanDefinitions(ele);
              }
          }
          
          protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
              // 解析 Bean 標(biāo)簽,創(chuàng)建 BeanDefinitionHolder 對象
              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));
              }
          }
          
          public static void registerBeanDefinition(
                  BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry)
                  throws BeanDefinitionStoreException {
          
              // Register bean definition under primary name.
              String beanName = definitionHolder.getBeanName();
              // 注冊 BeanDefinition 至于 DefaultListableBeanFactory 的 beanDefinitionMap 中
              registry.registerBeanDefinition(beanName, definitionHolder.getBeanDefinition());
          
              // Register aliases for bean name, if any.
              String[] aliases = definitionHolder.getAliases();
              if (aliases != null) {
                  for (String alias : aliases) {
                      registry.registerAlias(beanName, alias);
                  }
              }
          }
          
          // 自定義命名空間的解析衅码,如: context拯刁,aop,tx
          public BeanDefinition parseCustomElement(Element ele, @Nullable BeanDefinition containingBd) {
              String namespaceUri = getNamespaceURI(ele);
              if (namespaceUri == null) {
                  return null;
              }
              // 根據(jù) META-INF/spring.handlers 中的配置逝段,找到 Namespace 對應(yīng)的 Handler
              NamespaceHandler handler = this.readerContext.getNamespaceHandlerResolver().resolve(namespaceUri);
              if (handler == null) {
                  error("Unable to locate Spring NamespaceHandler for XML schema namespace [" + namespaceUri + "]", ele);
                  return null;
              }
              // 調(diào)用 NamespaceHandler 實現(xiàn)的 parse 方法將 dom element 解析為 BeanDefinition
              return handler.parse(ele, new ParserContext(this.readerContext, this, containingBd));
          }
          
          

        上述源碼流程即為 obtainFreshBeanFactory 的過程筛璧,主要完成了

        1. 創(chuàng)建了 DefaultListableBeanFactory;
        2. 讀取配置文件惹恃,完成了BeanDefinition的加載

        引申:
        在對自定義命名空間進(jìn)行處理時夭谤,會有一些預(yù)置的 BeanDefinition 的加載,例如對 context:annotation-config 標(biāo)簽處理時巫糙,會加載 ConfigurationClassPostProcessor 類(BeanFactoryPostProcessor)的 BeanDefinition, 在后續(xù) invokeBeanFactoryPostProcessors 方法中朗儒,會使用到該擴展點

        public class ContextNamespaceHandler extends NamespaceHandlerSupport {
        
            @Override
            public void init() {
                registerBeanDefinitionParser("property-placeholder", new PropertyPlaceholderBeanDefinitionParser());
                registerBeanDefinitionParser("property-override", new PropertyOverrideBeanDefinitionParser());
                // 對 @autowired、@ Resource 、@ PostConstruct醉锄、@ PreDestroy乏悄、@Required、@PersistenceContext 注解解析
                registerBeanDefinitionParser("annotation-config", new AnnotationConfigBeanDefinitionParser());
                // 除了annotation-config對應(yīng)的注解解析外恳不,擴展了 @Component 注解的支持檩小,因此如果配制了 context:component-scan 就無須再配置 context:annotation-config
                registerBeanDefinitionParser("component-scan", new ComponentScanBeanDefinitionParser());
                registerBeanDefinitionParser("load-time-weaver", new LoadTimeWeaverBeanDefinitionParser());
                registerBeanDefinitionParser("spring-configured", new SpringConfiguredBeanDefinitionParser());
                registerBeanDefinitionParser("mbean-export", new MBeanExportBeanDefinitionParser());
                registerBeanDefinitionParser("mbean-server", new MBeanServerBeanDefinitionParser());
            }
        
        }
        
      2. GenericApplicationContext::refreshBeanFactory
        GenericApplicationContext 的 refresh 方法相比于 AbstractRefreshableApplicationContext 要簡單許多,只有一個 refresh 標(biāo)記的判斷以及序列化 ID 的設(shè)置

        protected final void refreshBeanFactory() throws IllegalStateException {
            if (!this.refreshed.compareAndSet(false, true)) {
                throw new IllegalStateException(
                        "GenericApplicationContext does not support multiple refresh attempts: just call 'refresh' once");
            }
            this.beanFactory.setSerializationId(getId());
        }
        
        
總結(jié)

本篇文章中首先對 refresh 函數(shù)源碼進(jìn)行了簡單的分析烟勋,了解了各個函數(shù)大概的作用规求,然后針對 prepareRefresh 和 obtainFreshBeanFactory 函數(shù)做了詳細(xì)的分析。

  1. prepareRefresh
    在該函數(shù)中進(jìn)行了一些容器刷新的準(zhǔn)備卵惦,如記錄容器啟動時間阻肿、定義早期事件的監(jiān)聽器等
  2. obtainFreshBeanFactory
    AbstractApplicationContext 中該方法為空,在其子類 AbstractRefreshableApplicationContext 和 GenericApplicationContext 中對該方法進(jìn)行了擴展沮尿。
    • AbstractRefreshableApplicationContext
      方法中首先定義了 beanDefinitionReader丛塌,然后讀取配置文件將配置文件中定義的 Bean 信息加載為 BeanDefinition,需要注意的是其中包含一些自定義命名空間的解析畜疾。
    • GenericApplicationContext
      僅做了refresh 標(biāo)記的判斷以及序列化 ID 的設(shè)置
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末赴邻,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子啡捶,更是在濱河造成了極大的恐慌姥敛,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,188評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件届慈,死亡現(xiàn)場離奇詭異徒溪,居然都是意外死亡忿偷,警方通過查閱死者的電腦和手機金顿,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,464評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來鲤桥,“玉大人揍拆,你說我怎么就攤上這事〔璧剩” “怎么了嫂拴?”我有些...
    開封第一講書人閱讀 165,562評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長贮喧。 經(jīng)常有香客問我筒狠,道長,這世上最難降的妖魔是什么箱沦? 我笑而不...
    開封第一講書人閱讀 58,893評論 1 295
  • 正文 為了忘掉前任辩恼,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘灶伊。我一直安慰自己疆前,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,917評論 6 392
  • 文/花漫 我一把揭開白布聘萨。 她就那樣靜靜地躺著竹椒,像睡著了一般。 火紅的嫁衣襯著肌膚如雪米辐。 梳的紋絲不亂的頭發(fā)上胸完,一...
    開封第一講書人閱讀 51,708評論 1 305
  • 那天,我揣著相機與錄音儡循,去河邊找鬼舶吗。 笑死,一個胖子當(dāng)著我的面吹牛择膝,可吹牛的內(nèi)容都是我干的誓琼。 我是一名探鬼主播,決...
    沈念sama閱讀 40,430評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼肴捉,長吁一口氣:“原來是場噩夢啊……” “哼腹侣!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起齿穗,我...
    開封第一講書人閱讀 39,342評論 0 276
  • 序言:老撾萬榮一對情侶失蹤傲隶,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后窃页,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體跺株,經(jīng)...
    沈念sama閱讀 45,801評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,976評論 3 337
  • 正文 我和宋清朗相戀三年脖卖,在試婚紗的時候發(fā)現(xiàn)自己被綠了乒省。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,115評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡畦木,死狀恐怖袖扛,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情十籍,我是刑警寧澤蛆封,帶...
    沈念sama閱讀 35,804評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站勾栗,受9級特大地震影響惨篱,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜围俘,卻給世界環(huán)境...
    茶點故事閱讀 41,458評論 3 331
  • 文/蒙蒙 一砸讳、第九天 我趴在偏房一處隱蔽的房頂上張望机断。 院中可真熱鬧,春花似錦绣夺、人聲如沸吏奸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,008評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽奋蔚。三九已至,卻和暖如春烈钞,著一層夾襖步出監(jiān)牢的瞬間泊碑,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,135評論 1 272
  • 我被黑心中介騙來泰國打工毯欣, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留馒过,地道東北人。 一個月前我還...
    沈念sama閱讀 48,365評論 3 373
  • 正文 我出身青樓酗钞,卻偏偏與公主長得像腹忽,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子砚作,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,055評論 2 355

推薦閱讀更多精彩內(nèi)容