欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java Spring的refresh方法你知道嗎

 更新時(shí)間:2022年03月18日 11:12:15   作者:油頭怪  
這篇文章主要為大家詳細(xì)介紹了Java Spring的refresh方法,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來幫助

spring的refresh方法

前置知識

方法入口

// org.springframework.context.support.AbstractApplicationContext#refresh

類的結(jié)構(gòu)圖

在這里插入圖片描述

BeanDefinition 接口定義

public interface BeanDefinition extends AttributeAccessor, BeanMetadataElement {
   // 我們可以看到,默認(rèn)只提供 sington 和 prototype 兩種,
   // 很多讀者可能知道還有 request, session, globalSession, application, websocket 這幾種,
   // 不過,它們屬于基于 web 的擴(kuò)展。
   String SCOPE_SINGLETON = ConfigurableBeanFactory.SCOPE_SINGLETON;
   String SCOPE_PROTOTYPE = ConfigurableBeanFactory.SCOPE_PROTOTYPE;
   // 比較不重要,直接跳過吧
   int ROLE_APPLICATION = 0;
   int ROLE_SUPPORT = 1;
   int ROLE_INFRASTRUCTURE = 2;
   // 設(shè)置父 Bean,這里涉及到 bean 繼承,不是 java 繼承。請參見附錄的詳細(xì)介紹
   // 一句話就是:繼承父 Bean 的配置信息而已
   void setParentName(String parentName);
   // 獲取父 Bean
   String getParentName();
   // 設(shè)置 Bean 的類名稱,將來是要通過反射來生成實(shí)例的
   void setBeanClassName(String beanClassName);
   // 獲取 Bean 的類名稱
   String getBeanClassName();

   // 設(shè)置 bean 的 scope
   void setScope(String scope);
   String getScope();
   // 設(shè)置是否懶加載
   void setLazyInit(boolean lazyInit);
   boolean isLazyInit();
   // 設(shè)置該 Bean 依賴的所有的 Bean,注意,這里的依賴不是指屬性依賴(如 @Autowire 標(biāo)記的),
   // 是 depends-on="" 屬性設(shè)置的值。
   void setDependsOn(String... dependsOn);
   // 返回該 Bean 的所有依賴
   String[] getDependsOn();
   // 設(shè)置該 Bean 是否可以注入到其他 Bean 中,只對根據(jù)類型注入有效,
   // 如果根據(jù)名稱注入,即使這邊設(shè)置了 false,也是可以的
   void setAutowireCandidate(boolean autowireCandidate);
   // 該 Bean 是否可以注入到其他 Bean 中
   boolean isAutowireCandidate();
   // 主要的。同一接口的多個(gè)實(shí)現(xiàn),如果不指定名字的話,Spring 會優(yōu)先選擇設(shè)置 primary 為 true 的 bean
   void setPrimary(boolean primary);
   // 是否是 primary 的
   boolean isPrimary();
   // 如果該 Bean 采用工廠方法生成,指定工廠名稱。對工廠不熟悉的讀者,請參加附錄
   // 一句話就是:有些實(shí)例不是用反射生成的,而是用工廠模式生成的
   void setFactoryBeanName(String factoryBeanName);
   // 獲取工廠名稱
   String getFactoryBeanName();
   // 指定工廠類中的 工廠方法名稱
   void setFactoryMethodName(String factoryMethodName);
   // 獲取工廠類中的 工廠方法名稱
   String getFactoryMethodName();
   // 構(gòu)造器參數(shù)
   ConstructorArgumentValues getConstructorArgumentValues();
   // Bean 中的屬性值,后面給 bean 注入屬性值的時(shí)候會說到
   MutablePropertyValues getPropertyValues();
   // 是否 singleton
   boolean isSingleton();
   // 是否 prototype
   boolean isPrototype();
   // 如果這個(gè) Bean 是被設(shè)置為 abstract,那么不能實(shí)例化,
   // 常用于作為 父bean 用于繼承,其實(shí)也很少用......
   boolean isAbstract();
   int getRole();
   String getDescription();
   String getResourceDescription();
   BeanDefinition getOriginatingBeanDefinition();
}

refresh 這里簡單說下為什么是 refresh(),而不是 init() 這種名字的方法。因?yàn)?ApplicationContext 建立起來以后,其實(shí)我們是可以通過調(diào)用 refresh() 這個(gè)方法重建的,refresh() 會將原來的 ApplicationContext 銷毀,然后再重新執(zhí)行一次初始化操作。

@Override
public void refresh() throws BeansException, IllegalStateException {
   // 來個(gè)鎖,不然 refresh() 還沒結(jié)束,你又來個(gè)啟動(dòng)或銷毀容器的操作,那不就亂套了嘛
   synchronized (this.startupShutdownMonitor) {
      // 準(zhǔn)備工作,記錄下容器的啟動(dòng)時(shí)間、標(biāo)記“已啟動(dòng)”狀態(tài)、處理配置文件中的占位符
      prepareRefresh();
      // 這步比較關(guān)鍵,這步完成后,配置文件就會解析成一個(gè)個(gè) Bean 定義,注冊到 BeanFactory 中,
      // 當(dāng)然,這里說的 Bean 還沒有初始化,只是配置信息都提取出來了,
      // 注冊也只是將這些信息都保存到了注冊中心(說到底核心是一個(gè) beanName-> beanDefinition 的 map)
      ConfigurableListableBeanFactory beanFactory = obtainFreshBeanFactory();
      // 設(shè)置 BeanFactory 的類加載器,添加幾個(gè) BeanPostProcessor,手動(dòng)注冊幾個(gè)特殊的 bean
      // 這塊待會會展開說
      prepareBeanFactory(beanFactory);
      try {
         // 【這里需要知道 BeanFactoryPostProcessor 這個(gè)知識點(diǎn),Bean 如果實(shí)現(xiàn)了此接口,
         // 那么在容器初始化以后,Spring 會負(fù)責(zé)調(diào)用里面的 postProcessBeanFactory 方法?!?
         // 這里是提供給子類的擴(kuò)展點(diǎn),到這里的時(shí)候,所有的 Bean 都加載、注冊完成了,但是都還沒有初始化
         // 具體的子類可以在這步的時(shí)候添加一些特殊的 BeanFactoryPostProcessor 的實(shí)現(xiàn)類或做點(diǎn)什么事
         postProcessBeanFactory(beanFactory);
         // 調(diào)用 BeanFactoryPostProcessor 各個(gè)實(shí)現(xiàn)類的 postProcessBeanFactory(factory) 方法
         invokeBeanFactoryPostProcessors(beanFactory);
         // 注冊 BeanPostProcessor 的實(shí)現(xiàn)類,注意看和 BeanFactoryPostProcessor 的區(qū)別
         // 此接口兩個(gè)方法: postProcessBeforeInitialization 和 postProcessAfterInitialization
         // 兩個(gè)方法分別在 Bean 初始化之前和初始化之后得到執(zhí)行。注意,到這里 Bean 還沒初始化
         registerBeanPostProcessors(beanFactory);
         // 初始化當(dāng)前 ApplicationContext 的 MessageSource,國際化這里就不展開說了,不然沒完沒了了
         initMessageSource();
         // 初始化當(dāng)前 ApplicationContext 的事件廣播器,這里也不展開了
         initApplicationEventMulticaster();
         // 從方法名就可以知道,典型的模板方法(鉤子方法),
         // 具體的子類可以在這里初始化一些特殊的 Bean(在初始化 singleton beans 之前)
         onRefresh();
         // 注冊事件監(jiān)聽器,監(jiān)聽器需要實(shí)現(xiàn) ApplicationListener 接口。這也不是我們的重點(diǎn),過
         registerListeners();
         // 重點(diǎn),重點(diǎn),重點(diǎn)
         // 初始化所有的 singleton beans
         //(lazy-init 的除外)
         finishBeanFactoryInitialization(beanFactory);
         // 最后,廣播事件,ApplicationContext 初始化完成
         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.
         // 銷毀已經(jīng)初始化的 singleton 的 Beans,以免有些 bean 會一直占用資源
         destroyBeans();
         // Reset 'active' flag.
         cancelRefresh(ex);
         // 把異常往外拋
         throw ex;
      }
      finally {
         // Reset common introspection caches in Spring's core, since we
         // might not ever need metadata for singleton beans anymore...
         resetCommonCaches();
      }
   }
}

創(chuàng)建 Bean 容器前的準(zhǔn)備工作

// 準(zhǔn)備工作
protected void prepareRefresh() {
   // 記錄啟動(dòng)時(shí)間,
   // 將 active 屬性設(shè)置為 true,closed 屬性設(shè)置為 false,它們都是 AtomicBoolean 類型
   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 初始化上下文環(huán)境中的任何占位符屬性源。
   initPropertySources();
   // 校驗(yàn) xml 配置文件
   getEnvironment().validateRequiredProperties();
   // 初始化事件集合
   this.earlyApplicationEvents = new LinkedHashSet<ApplicationEvent>();
}

創(chuàng)建 Bean 容器,加載并注冊 Bean

// 最重要的方法之一,這里將會初始化 BeanFactory、加載 Bean、注冊 Bean 等等。
protected ConfigurableListableBeanFactory obtainFreshBeanFactory() {
   // 關(guān)閉舊的 BeanFactory (如果有),創(chuàng)建新的 BeanFactory,加載 Bean 定義、注冊 Bean 等等
   refreshBeanFactory();
   // 返回剛剛創(chuàng)建的 BeanFactory
   ConfigurableListableBeanFactory beanFactory = getBeanFactory();
   if (logger.isDebugEnabled()) {
      logger.debug("Bean factory for " + getDisplayName() + ": " + beanFactory);
   }
   return beanFactory;
}
// refreshBeanFactory
@Override
protected final void refreshBeanFactory() throws BeansException {
   // 如果 ApplicationContext 中已經(jīng)加載過 BeanFactory 了,銷毀所有 Bean,關(guān)閉 BeanFactory
   // 注意,應(yīng)用中 BeanFactory 本來就是可以多個(gè)的,這里可不是說應(yīng)用全局是否有 BeanFactory,而是當(dāng)前
   // ApplicationContext 是否有 BeanFactory
   if (hasBeanFactory()) {
      destroyBeans();
      closeBeanFactory();
   }
   try {
      // 初始化一個(gè) DefaultListableBeanFactory,為什么用這個(gè),我們馬上說。
      DefaultListableBeanFactory beanFactory = createBeanFactory();
      // 用于 BeanFactory 的序列化,我想大部分人應(yīng)該都用不到
      beanFactory.setSerializationId(getId());
      // 下面這兩個(gè)方法很重要,別跟丟了,具體細(xì)節(jié)之后說
      // 設(shè)置 BeanFactory 的兩個(gè)配置屬性:是否允許 Bean 覆蓋、是否允許循環(huán)引用
      customizeBeanFactory(beanFactory);
      // 加載 Bean 到 BeanFactory 中
      loadBeanDefinitions(beanFactory);
      synchronized (this.beanFactoryMonitor) {
         this.beanFactory = beanFactory;
      }
   }
   catch (IOException ex) {
      throw new ApplicationContextException("I/O error parsing bean definition source for " + getDisplayName(), ex);
   }
}
// customizeBeanFactory 配置是否允許 BeanDefinition 覆蓋、是否允許循環(huán)引用。
protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
   if (this.allowBeanDefinitionOverriding != null) {
      // 是否允許 Bean 定義覆蓋  在配置文件中定義 bean 時(shí)使用了相同的 id 或 name,默認(rèn)情況下,allowBeanDefinitionOverriding 屬性為 null,如果在同一配置文件中重復(fù)了,會拋錯(cuò),但是如果不是同一配置文件中,會發(fā)生覆蓋。
      beanFactory.setAllowBeanDefinitionOverriding(this.allowBeanDefinitionOverriding);
   }
   if (this.allowCircularReferences != null) {
      // 是否允許 Bean 間的循環(huán)依賴  如:A 依賴 B,而 B 依賴 A?;?A 依賴 B,B 依賴 C,而 C 依賴 A。
      beanFactory.setAllowCircularReferences(this.allowCircularReferences);
   }
}
// loadBeanDefinitions 加載bean,放入 BeanFactory 中 org.springframework.context.support.AbstractXmlApplicationContext#loadBeanDefinitions(org.springframework.beans.factory.support.DefaultListableBeanFactory)
/** 我們可以看到,此方法將通過一個(gè) XmlBeanDefinitionReader 實(shí)例來加載各個(gè) Bean。*/
@Override
protected void loadBeanDefinitions(DefaultListableBeanFactory beanFactory) throws BeansException, IOException {
   // 給這個(gè) BeanFactory 實(shí)例化一個(gè) XmlBeanDefinitionReader
   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));
   // 初始化 BeanDefinitionReader,其實(shí)這個(gè)是提供給子類覆寫的,
   // 我看了一下,沒有類覆寫這個(gè)方法,我們姑且當(dāng)做不重要吧
   initBeanDefinitionReader(beanDefinitionReader);
   // 重點(diǎn)來了,繼續(xù)往下
   loadBeanDefinitions(beanDefinitionReader);
}
protected void loadBeanDefinitions(XmlBeanDefinitionReader reader) throws BeansException, IOException {
   Resource[] configResources = getConfigResources();
   if (configResources != null) {
      // 往下看
      reader.loadBeanDefinitions(configResources);
   }
   String[] configLocations = getConfigLocations();
   if (configLocations != null) {
      // 2
      reader.loadBeanDefinitions(configLocations);
   }
}
// 上面雖然有兩個(gè)分支,不過第二個(gè)分支很快通過解析路徑轉(zhuǎn)換為 Resource 以后也會進(jìn)到這里
@Override
public int loadBeanDefinitions(Resource... resources) throws BeanDefinitionStoreException {
   Assert.notNull(resources, "Resource array must not be null");
   int counter = 0;
   // 注意這里是個(gè) for 循環(huán),也就是每個(gè)文件是一個(gè) resource
   for (Resource resource : resources) {
      // 繼續(xù)往下看
      counter += loadBeanDefinitions(resource);
   }
   // 最后返回 counter,表示總共加載了多少的 BeanDefinition
   return counter;
}
// XmlBeanDefinitionReader 303
@Override
public int loadBeanDefinitions(Resource resource) throws BeanDefinitionStoreException {
   return loadBeanDefinitions(new EncodedResource(resource));
}
// XmlBeanDefinitionReader 314
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());
   }
   // 用一個(gè) ThreadLocal 來存放配置文件資源
   Set<EncodedResource> currentResources = this.resourcesCurrentlyBeingLoaded.get();
   if (currentResources == null) {
      currentResources = new HashSet<EncodedResource>(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();
      }
   }
}
// 還在這個(gè)文件中,第 388 行
protected int doLoadBeanDefinitions(InputSource inputSource, Resource resource)
      throws BeanDefinitionStoreException {
   try {
      // 這里就不看了,將 xml 文件轉(zhuǎn)換為 Document 對象
      Document doc = doLoadDocument(inputSource, resource);
      // 繼續(xù)
      return registerBeanDefinitions(doc, resource);
   }
   catch (...
}
// 還在這個(gè)文件中,第 505 行
// 返回值:返回從當(dāng)前配置文件加載了多少數(shù)量的 Bean
public int registerBeanDefinitions(Document doc, Resource resource) throws BeanDefinitionStoreException {
   BeanDefinitionDocumentReader documentReader = createBeanDefinitionDocumentReader();
   int countBefore = getRegistry().getBeanDefinitionCount();
   // 這里
   documentReader.registerBeanDefinitions(doc, createReaderContext(resource));
   return getRegistry().getBeanDefinitionCount() - countBefore;
}
// DefaultBeanDefinitionDocumentReader 90
@Override
public void registerBeanDefinitions(Document doc, XmlReaderContext readerContext) {
   this.readerContext = readerContext;
   logger.debug("Loading bean definitions");
   Element root = doc.getDocumentElement();
   // 從 xml 根節(jié)點(diǎn)開始解析文件
   doRegisterBeanDefinitions(root);
}     
// doRegisterBeanDefinitions 經(jīng)過漫長的鏈路,一個(gè)配置文件終于轉(zhuǎn)換為一顆 DOM 樹了,注意,這里指的是其中一個(gè)配置文件,不是所有的,讀者可以看到上面有個(gè) for 循環(huán)的。下面開始從根節(jié)點(diǎn)開始解析:
// DefaultBeanDefinitionDocumentReader 116
protected void doRegisterBeanDefinitions(Element root) {
   // 我們看名字就知道,BeanDefinitionParserDelegate 必定是一個(gè)重要的類,它負(fù)責(zé)解析 Bean 定義,
   // 這里為什么要定義一個(gè) parent? 看到后面就知道了,是遞歸問題,
   // 因?yàn)?<beans /> 內(nèi)部是可以定義 <beans /> 的,所以這個(gè)方法的 root 其實(shí)不一定就是 xml 的根節(jié)點(diǎn),也可以是嵌套在里面的 <beans /> 節(jié)點(diǎn),從源碼分析的角度,我們當(dāng)做根節(jié)點(diǎn)就好了
   BeanDefinitionParserDelegate parent = this.delegate;
   this.delegate = createDelegate(getReaderContext(), root, parent);
   if (this.delegate.isDefaultNamespace(root)) {
      // 這塊說的是根節(jié)點(diǎn) <beans ... profile="dev" /> 中的 profile 是否是當(dāng)前環(huán)境需要的,
      // 如果當(dāng)前環(huán)境配置的 profile 不包含此 profile,那就直接 return 了,不對此 <beans /> 解析
      // 不熟悉 profile 為何物,不熟悉怎么配置 profile 讀者的請移步附錄區(qū)
      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); // 鉤子 preProcessXml(root) 和 postProcessXml(root) 是給子類用的鉤子方法,鑒于沒有被使用到,也不是我們的重點(diǎn),我們直接跳過。
   // 往下看
   parseBeanDefinitions(root, this.delegate);
   postProcessXml(root); // 鉤子
   this.delegate = parent;
}
// default namespace 涉及到的就四個(gè)標(biāo)簽 <import />、<alias />、<bean /> 和 <beans />,
// 其他的屬于 custom 的
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)) {
               // 解析 default namespace 下面的幾個(gè)元素
               parseDefaultElement(ele, delegate);
            }
            else {
               // 解析其他 namespace 的元素
               delegate.parseCustomElement(ele);
            }
         }
      }
   }
   else {
      delegate.parseCustomElement(root);
   }
}          
private void parseDefaultElement(Element ele, BeanDefinitionParserDelegate delegate) {
   if (delegate.nodeNameEquals(ele, IMPORT_ELEMENT)) {
      // 處理 <import /> 標(biāo)簽
      importBeanDefinitionResource(ele);
   }
   else if (delegate.nodeNameEquals(ele, ALIAS_ELEMENT)) {
      // 處理 <alias /> 標(biāo)簽定義
      // <alias name="fromName" alias="toName"/>
      processAliasRegistration(ele);
   }
   else if (delegate.nodeNameEquals(ele, BEAN_ELEMENT)) {
      // 處理 <bean /> 標(biāo)簽定義,這也算是我們的重點(diǎn)吧
      processBeanDefinition(ele, delegate);
   }
   else if (delegate.nodeNameEquals(ele, NESTED_BEANS_ELEMENT)) {
      // 如果碰到的是嵌套的 <beans /> 標(biāo)簽,需要遞歸
      doRegisterBeanDefinitions(ele);
   }
}          
// DefaultBeanDefinitionDocumentReader 298
protected void processBeanDefinition(Element ele, BeanDefinitionParserDelegate delegate) {
   // 將 <bean /> 節(jié)點(diǎn)中的信息提取出來,然后封裝到一個(gè) BeanDefinitionHolder 中,細(xì)節(jié)往下看
   BeanDefinitionHolder bdHolder = delegate.parseBeanDefinitionElement(ele);
   // 下面的幾行先不要看,跳過先,跳過先,跳過先,后面會繼續(xù)說的
   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));
   }
}  
// BeanDefinitionParserDelegate 428
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele) {
    return parseBeanDefinitionElement(ele, null);
}
public BeanDefinitionHolder parseBeanDefinitionElement(Element ele, BeanDefinition containingBean) {
   String id = ele.getAttribute(ID_ATTRIBUTE);
   String nameAttr = ele.getAttribute(NAME_ATTRIBUTE);
   List<String> aliases = new ArrayList<String>();
   // 將 name 屬性的定義按照 “逗號、分號、空格” 切分,形成一個(gè) 別名列表數(shù)組,
   // 當(dāng)然,如果你不定義 name 屬性的話,就是空的了
   // 我在附錄中簡單介紹了一下 id 和 name 的配置,大家可以看一眼,有個(gè)20秒就可以了
   if (StringUtils.hasLength(nameAttr)) {
      String[] nameArr = StringUtils.tokenizeToStringArray(nameAttr, MULTI_VALUE_ATTRIBUTE_DELIMITERS);
      aliases.addAll(Arrays.asList(nameArr));
   }
   String beanName = id;
   // 如果沒有指定id, 那么用別名列表的第一個(gè)名字作為beanName
   if (!StringUtils.hasText(beanName) && !aliases.isEmpty()) {
      beanName = aliases.remove(0);
      if (logger.isDebugEnabled()) {
         logger.debug("No XML 'id' specified - using '" + beanName +
               "' as bean name and " + aliases + " as aliases");
      }
   }
   if (containingBean == null) {
      checkNameUniqueness(beanName, aliases, ele);
   }
   // 根據(jù) <bean ...>...</bean> 中的配置創(chuàng)建 BeanDefinition,然后把配置中的信息都設(shè)置到實(shí)例中,
   // 細(xì)節(jié)后面細(xì)說,先知道下面這行結(jié)束后,一個(gè) BeanDefinition 實(shí)例就出來了。
   AbstractBeanDefinition beanDefinition = parseBeanDefinitionElement(ele, beanName, containingBean);
   // 到這里,整個(gè) <bean /> 標(biāo)簽就算解析結(jié)束了,一個(gè) BeanDefinition 就形成了。
   if (beanDefinition != null) {
      // 如果都沒有設(shè)置 id 和 name,那么此時(shí)的 beanName 就會為 null,進(jìn)入下面這塊代碼產(chǎn)生
      // 如果讀者不感興趣的話,我覺得不需要關(guān)心這塊代碼,對本文源碼分析來說,這些東西不重要
      if (!StringUtils.hasText(beanName)) {
         try {
            if (containingBean != null) {// 按照我們的思路,這里 containingBean 是 null 的
               beanName = BeanDefinitionReaderUtils.generateBeanName(
                     beanDefinition, this.readerContext.getRegistry(), true);
            }
            else {
               // 如果我們不定義 id 和 name,那么我們引言里的那個(gè)例子:
               //   1. beanName 為:com.javadoop.example.MessageServiceImpl#0
               //   2. beanClassName 為:com.javadoop.example.MessageServiceImpl
               beanName = this.readerContext.generateBeanName(beanDefinition);
               String beanClassName = beanDefinition.getBeanClassName();
               if (beanClassName != null &&
                     beanName.startsWith(beanClassName) && beanName.length() > beanClassName.length() &&
                     !this.readerContext.getRegistry().isBeanNameInUse(beanClassName)) {
                  // 把 beanClassName 設(shè)置為 Bean 的別名
                  aliases.add(beanClassName);
               }
            }
            if (logger.isDebugEnabled()) {
               logger.debug("Neither XML 'id' nor 'name' specified - " +
                     "using generated bean name [" + beanName + "]");
            }
         }
         catch (Exception ex) {
            error(ex.getMessage(), ele);
            return null;
         }
      }
      String[] aliasesArray = StringUtils.toStringArray(aliases);
      // 返回 BeanDefinitionHolder
      return new BeanDefinitionHolder(beanDefinition, beanName, aliasesArray);
   }
   return null;
}          

看到這里的時(shí)候,我覺得讀者就應(yīng)該站在高處看 ApplicationContext 了,ApplicationContext 繼承自 BeanFactory,但是它不應(yīng)該被理解為 BeanFactory 的實(shí)現(xiàn)類,而是說其內(nèi)部持有一個(gè)實(shí)例化的 BeanFactory(DefaultListableBeanFactory)。以后所有的 BeanFactory 相關(guān)的操作其實(shí)是委托給這個(gè)實(shí)例來處理的。

我們說說為什么選擇實(shí)例化 DefaultListableBeanFactory ?前面我們說了有個(gè)很重要的接口 ConfigurableListableBeanFactory,它實(shí)現(xiàn)了 BeanFactory 下面一層的所有三個(gè)接口,我把之前的繼承圖再拿過來大家再仔細(xì)看一下:

在這里插入圖片描述

我們可以看到 ConfigurableListableBeanFactory 只有一個(gè)實(shí)現(xiàn)類DefaultListableBeanFactory,而且實(shí)現(xiàn)類 DefaultListableBeanFactory 還通過實(shí)現(xiàn)右邊的 AbstractAutowireCapableBeanFactory 通吃了右路。所以結(jié)論就是,最底下這個(gè)家伙 DefaultListableBeanFactory 基本上是最牛的 BeanFactory 了,這也是為什么這邊會使用這個(gè)類來實(shí)例化的原因。

循環(huán)依賴

在這里插入圖片描述

總結(jié)

本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!    

相關(guān)文章

  • Springboot?2.x?RabbitTemplate默認(rèn)消息持久化的原因解析

    Springboot?2.x?RabbitTemplate默認(rèn)消息持久化的原因解析

    這篇文章主要介紹了Springboot?2.x?RabbitTemplate默認(rèn)消息持久化的原因解析,本文通過示例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-03-03
  • java圖片對比度調(diào)整示例代碼

    java圖片對比度調(diào)整示例代碼

    這篇文章主要給大家介紹了關(guān)于java圖片對比度調(diào)整的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用java具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-07-07
  • Java Collection集合iterator方法解析

    Java Collection集合iterator方法解析

    這篇文章主要介紹了Java Collection集合iterator方法解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-01-01
  • 10個(gè)實(shí)現(xiàn)Java集合,Map類型自由轉(zhuǎn)換的實(shí)用工具方法

    10個(gè)實(shí)現(xiàn)Java集合,Map類型自由轉(zhuǎn)換的實(shí)用工具方法

    這篇文章主要為大家整理了整理了10個(gè)實(shí)用工具方法,可以滿足?Collection、List、Set、Map?之間各種類型轉(zhuǎn)化,文中的示例代碼講解詳細(xì),需要的可以參考下
    2023-09-09
  • Java的反射機(jī)制之類加載詳解

    Java的反射機(jī)制之類加載詳解

    這篇文章主要介紹了Java的反射機(jī)制之類加載詳解,反射機(jī)制是java實(shí)現(xiàn)動(dòng)態(tài)語言的關(guān)鍵,也就是通過反射實(shí)現(xiàn)類動(dòng)態(tài)加載,靜態(tài)加載是指在編譯時(shí)期確定要加載的類的類型,即通過class關(guān)鍵字和類名來獲取對應(yīng)類的類型,需要的朋友可以參考下
    2023-09-09
  • Spring boot打包jar分離lib和resources方法實(shí)例

    Spring boot打包jar分離lib和resources方法實(shí)例

    這篇文章主要介紹了Spring boot打包jar分離lib和resources方法實(shí)例,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-05-05
  • 面試題:Java 實(shí)現(xiàn)查找旋轉(zhuǎn)數(shù)組的最小數(shù)字

    面試題:Java 實(shí)現(xiàn)查找旋轉(zhuǎn)數(shù)組的最小數(shù)字

    這篇文章主要介紹了Java 實(shí)現(xiàn)查找旋轉(zhuǎn)數(shù)組的最小數(shù)字,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-07-07
  • 基于eclipse.ini內(nèi)存設(shè)置的問題詳解

    基于eclipse.ini內(nèi)存設(shè)置的問題詳解

    本篇文章是對eclipse.ini內(nèi)存設(shè)置的問題進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-05-05
  • Spring boot 跳轉(zhuǎn)到j(luò)sp頁面的實(shí)現(xiàn)方法

    Spring boot 跳轉(zhuǎn)到j(luò)sp頁面的實(shí)現(xiàn)方法

    本篇文章主要介紹了Spring boot 跳轉(zhuǎn)到j(luò)sp頁面的實(shí)現(xiàn)方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-04-04
  • 導(dǎo)入SpringCloud依賴踩的坑及解決

    導(dǎo)入SpringCloud依賴踩的坑及解決

    這篇文章主要介紹了導(dǎo)入SpringCloud依賴踩的坑及解決方案,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-04-04

最新評論