关联博文:
AbstractApplicationContext中refresh方法详解
Spring中refresh分析之prepareRefresh方法详解
Spring中refresh分析之obtainFreshBeanFactory方法详解
Spring中refresh分析之prepareBeanFactory方法详解
Spring中refresh分析之postProcessBeanFactory方法详解
Spring中refresh分析之invokeBeanFactoryPostProcessors方法详解
Spring中refresh分析之registerBeanPostProcessors方法详解
Spring中refresh分析之initMessageSource方法详解
Spring中refresh分析之initApplicationEventMulticaster方法详解
Spring中refresh分析之onRefresh方法详解
Spring中refresh分析之registerListeners方法详解
Spring中refresh分析之finishBeanFactoryInitialization方法详解
Spring中refresh分析之finishRefresh方法详解
接上文Spring中refresh分析之registerBeanPostProcessors方法详解我们分析过registerBeanPostProcessors后,本文分析initMessageSource方法。
MessageSource 是用来处理国际化的,该方法将会初始化MessageSource并尝试设置parentMessageSource,然后作为单例bean注册到容器中。通常注册是DelegatingMessageSource 实例。
AbstractApplicationContext的initMessageSource方法如下所示。
protected void initMessageSource() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
// messageSource
if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {
this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);
// Make MessageSource aware of parent MessageSource.
if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) {
HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource;
if (hms.getParentMessageSource() == null) {
// Only set parent context as parent MessageSource if no parent MessageSource
// registered already.
hms.setParentMessageSource(getInternalParentMessageSource());
}
}
if (logger.isTraceEnabled()) {
logger.trace("Using MessageSource [" + this.messageSource + "]");
}
}
else {
// Use empty MessageSource to be able to accept getMessage calls.
//实例化DelegatingMessageSource
DelegatingMessageSource dms = new DelegatingMessageSource();
//设置父消息源
dms.setParentMessageSource(getInternalParentMessageSource());
this.messageSource = dms;
//注册单例bean
beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);
if (logger.isTraceEnabled()) {
logger.trace("No '" + MESSAGE_SOURCE_BEAN_NAME + "' bean, using [" + this.messageSource + "]");
}
}
}
getInternalParentMessageSource
AbstractApplicationContext
的getInternalParentMessageSource
方法如下所示,如果父上下文也是AbstractApplicationContext,则返回父上下文的内部消息源;否则,返回父上下文本身。
@Nullable
protected MessageSource getInternalParentMessageSource() {
return (getParent() instanceof AbstractApplicationContext ?
((AbstractApplicationContext) getParent()).messageSource : getParent());
}
DelegatingMessageSource如下所示,内部维护了一个MessageSource parentMessageSource
。
HierarchicalMessageSource
主要提供了设置父消息的操作。此接口用于当消息源不能解决给定消息时,尝试使用父消息源解决消息,即层级解决消息。
MessageSourceSupport
内部主要成员为消息格式缓存Map<String, Map<Locale, MessageFormat>> messageFormatsPerMessage = new HashMap<>()
用于存储消息的消息格式, 以及是否应用消息格式规则,解析没有参数的消息标志alwaysUseMessageFormat。此消息源实现基础类主要提供了根据给定的消息,消息参数和本地化渲染消息操作,即使用参数替代默认消息中的占位符。
DelegatingMessageSource
内部有一父消息源,获取编码消息操作直接委托给父类数据源,如果没有父消息源,同时有默认消息,则使用消息参数 渲染默认消息,并返回。如果没有父消息可用且没有默认消息源,不会解决任何消息,抛出异常。代理消息源用于上下文没有定义消息源情况下,AbstractApplicationContext 使用 DelegatingMessageSource为消息源的占位符,此代理消息源不能被应用直接使用。