Spring原始碼 11 IOC refresh方法7
阿新 • • 發佈:2022-03-14
Spring IOC 的核心是
AbstractApplicationContext
的refresh
方法。
其中一共有 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();
}