1. 程式人生 > 其它 >Spring原始碼 11 IOC refresh方法7

Spring原始碼 11 IOC refresh方法7

Spring IOC 的核心是 AbstractApplicationContextrefresh 方法。
其中一共有 13 個主要方法,這裡分析第 7 個:initMessageSource

1 AbstractApplicationContext

1-1 初始化 message 源

initMessageSource()
protected void initMessageSource() {
   // 獲取 Bean 工廠
   ConfigurableListableBeanFactory beanFactory = getBeanFactory();
   if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {
      // 如果在配置中已經配置了 messageSource,那麼將 messageSource 提取並記錄在 this.messageSource 中
      this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);
      if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) {
         HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource;
         if (hms.getParentMessageSource() == null) {
            hms.setParentMessageSource(getInternalParentMessageSource());
         }
      }
      if (logger.isTraceEnabled()) {
         logger.trace("Using MessageSource [" + this.messageSource + "]");
      }
   } else {
      // 如果使用者並沒有定義配置檔案,那麼使用臨時的 DelegatingMessageSource 以便於作為呼叫 getMessage 方法的返回
      DelegatingMessageSource dms = new DelegatingMessageSource();
      dms.setParentMessageSource(getInternalParentMessageSource());
      this.messageSource = dms;
      // 註冊單例
      beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);
      if (logger.isTraceEnabled()) {
         logger.trace("No '" + MESSAGE_SOURCE_BEAN_NAME + "' bean, using [" + this.messageSource + "]");
      }
   }
}

1-2 獲取 Bean 工廠

getBeanFactory()

2 AbstractRefreshableApplicationContext

public final ConfigurableListableBeanFactory getBeanFactory() {
   DefaultListableBeanFactory beanFactory = this.beanFactory;
   if (beanFactory == null) {
      throw new IllegalStateException("BeanFactory not initialized or already closed - " + "call 'refresh' before accessing beans via the ApplicationContext");
   }
   return beanFactory;
}

if (beanFactory == null) 由於 beanFactory 已經被賦值,直接返回。

1 AbstractApplicationContext

1-2 註冊單例

registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource)

3 DefaultListableBeanFactory

public void registerSingleton(String beanName, Object singletonObject) throws IllegalStateException {
   // 呼叫父類方法
   super.registerSingleton(beanName, singletonObject);
   // 手動更新單例名稱
   updateManualSingletonNames(set -> set.add(beanName), set -> !this.beanDefinitionMap.containsKey(beanName));
   // 按型別清除快取
   clearByTypeCache();
}

3-1 呼叫父類方法

super.registerSingleton(beanName, singletonObject)

4 DefaultSingletonBeanRegistry

public void registerSingleton(String beanName, Object singletonObject) throws IllegalStateException {
   Assert.notNull(beanName, "Bean name must not be null");
   Assert.notNull(singletonObject, "Singleton object must not be null");
   synchronized (this.singletonObjects) {
      Object oldObject = this.singletonObjects.get(beanName);
      if (oldObject != null) {
         throw new IllegalStateException("Could not register object [" + singletonObject +
               "] under bean name '" + beanName + "': there is already object [" + oldObject + "] bound");
      }
      // 新增單例
      addSingleton(beanName, singletonObject);
   }
}

4-1 新增單例

addSingleton(beanName, singletonObject)
protected void addSingleton(String beanName, Object singletonObject) {
   synchronized (this.singletonObjects) {
      this.singletonObjects.put(beanName, singletonObject);
      this.singletonFactories.remove(beanName);
      this.earlySingletonObjects.remove(beanName);
      this.registeredSingletons.add(beanName);
   }
}

3 DefaultListableBeanFactory

3-1 手動更新單例名稱

updateManualSingletonNames(set -> set.add(beanName), set -> !this.beanDefinitionMap.containsKey(beanName))
private void updateManualSingletonNames(Consumer<Set<String>> action, Predicate<Set<String>> condition) {
   // 如果已開始建立 Bean
   if (hasBeanCreationStarted()) {
      // Cannot modify startup-time collection elements anymore (for stable iteration)
      synchronized (this.beanDefinitionMap) {
         if (condition.test(this.manualSingletonNames)) {
            Set<String> updatedSingletons = new LinkedHashSet<>(this.manualSingletonNames);
            action.accept(updatedSingletons);
            this.manualSingletonNames = updatedSingletons;
         }
      }
   }
   else {
      // Still in startup registration phase
      if (condition.test(this.manualSingletonNames)) {
         action.accept(this.manualSingletonNames);
      }
   }
}

3-2 判斷是否已開始建立 Bean

private final Set<String> alreadyCreated = Collections.newSetFromMap(new ConcurrentHashMap<>(256));

protected boolean hasBeanCreationStarted() {
   return !this.alreadyCreated.isEmpty();
}

3-1 按型別清除快取

clearByTypeCache()
private void clearByTypeCache() {
   this.allBeanNamesByType.clear();
   this.singletonBeanNamesByType.clear();
}