最近的几篇文档都在解析refresh()方法,按照代码的实现逻辑,接下来该分析的是initMessageSource()方法,但是这个方法的实现非常简单,无非是往spring容器里面注册了相关的主键,具体的实现都在组件里面,但是我们现在只分析spring的主流程,为了保证文章的连贯性,这里我们只分析initMessageSource方法的作用,和spring中国际化的使用,关于组件的具体实现,我们放在主流程分析完后再进行分析。
initMessageSource
protected void initMessageSource() {
ConfigurableListableBeanFactory beanFactory = getBeanFactory();
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 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 + "]");
}
}
}
这一个方法其实只做了一件事,就是给AbstractApplicationContext#messageSource赋值,先是从bdmap中找beanName为messageSource的bean,如果找不到则示例化一个DelegatingMessageSource 赋值给AbstractApplicationContext#messageSource
国际化的使用
使用spring中的国际化,通常会给往bdMap中注册进一个ResourceBundleMessageSource,下面会总spring国际化的使用过程,例子中使用了直接注册bd的方式注入的ResourceBundleMessageSource,当然这里你可以使用扫描等各种方式
public class TestI18n {
public static void main(String[] args) {
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext();
GenericBeanDefinition genericBeanDefinition = new GenericBeanDefinition();
genericBeanDefinition.setBeanClass(ResourceBundleMessageSource.class);
MutablePropertyValues propertyValues = new MutablePropertyValues();
// ResourceBundleMessageSource的basename属性用来表示文件的路径 i18为文件夹名,messages为文件前缀
propertyValues.add("basename", "i18n/messages");
genericBeanDefinition.setPropertyValues(propertyValues);
ac.registerBeanDefinition("messageSource",genericBeanDefinition);
ac.refresh();
String message = ac.getMessage("welcome", null, Locale.US);
System.out.println(message);
}
}
配置文件
由于 String message = ac.getMessage(“welcome”, null, Locale.US); 指定要获取英语的格式,所以讲从
messages_en_US.properties中读取
两个文件中的内容如下
所以执行的结果应该如下