背景
为了友好的支持各个国家的语言,Java 本身已经提供了对国际化的支持,上篇文章《Java 国际化与文本格式化》已经介绍了 Java 对国际化的支持。Java 对国际化的支持主要是使用 ResourceBundle 根据区域信息选取不同的 properties 文件获取 key 对应的 value,并且 Java 还提供了 MessageFormat 来支持对消息的格式化,Spring 将这两者进行结合,抽象出了 MessageSource 接口,使我们更方便的在 Spring 中获取国际化消息。
Spring 中的 MessageSource 接口
MessageSource 接口定义
认识 Spring 国际化支持,先从 MessageSource 接口看起,这是 Spring 国际化的核心接口,其定义如下。
public interface MessageSource { @Nullable String getMessage(String code, @Nullable Object[] args, @Nullable String defaultMessage, Locale locale); String getMessage(String code, @Nullable Object[] args, Locale locale) throws NoSuchMessageException; String getMessage(MessageSourceResolvable resolvable, Locale locale) throws NoSuchMessageException; }
MessageSource 接口提供了三个获取国际化消息的方法,其主要是根据 Locale 信息获取对应的国际化消息的集合,然后根据 code 获取对应的消息,并且通过提供的参数 args 还可以对获取后的消息进行格式化。具体参数含义如下。
code:要查找的消息编号。
args:为消息中的参数填充的值。
defaultMessage:默认的消息,如果没有找到将返回默认消息。
resolvable:消息参数,封装了 code、args、defaultMessage。
MessageSource 主要实现
MessageSource 在 Spring 中主要有两个实现,具体如下。
ResourceBundleMessageSource:底层使用 ResourceBundle 和 MessageFormat 实现的 MessageSource。
ReloadableResourceBundleMessageSource:支持国际化文件动态刷新的 MessageSource。
DelegatingMessageSource:代理父 MessageSource 的 MessageSource,获取消息时将委托父 MessageSource 获取,这是 Spring 应用上下文默认创建的 MessageSource。
如何在 Spring 中获取 MessageSource
我们经常说 Spring 的基础容器是 BeanFactory,ApplicationContext 是对 BeanFactory,提供了企业级的特性,其中就包括了对国际化的支持,这是因为 ApplicationContext 接口就继承了 MessageSource 接口,因此就可以认为 ApplicationContext 就是 MessageSource ,在 Spring 应用上下文刷新时将调用 AbstractApplicationContext#initMessageSource 初始化 MessageSource,这将保证 Spring 中一定存在一个类型为 MessageSource 的 bean,ApplicationContext 底层正是依托这个 bean 来实现 MessageSource 接口的方法。因此具有以下的方法获取 MessageSource。
依赖查找 MessageSource,其中 bean 的名称为 messageSource,即AbstractApplicationContext#MESSAGE_SOURCE_BEAN_NAME。
依赖注入 MessageSource。
直接使用 ApplicationContext。
通过 MessageSourceAware 回调获取。