前言

在阅读完 registerBeanPostProcessors 源码之后, 下一步就进入到 initMessageSource,这一步主要作用是初始化国际化文件。
依然如之前所示,先通过官网了解到国际化的用法,然后再对源码进行研究。

MessageSource 国际化

13-Spring initMessageSource - 图1
如官网1.15.1. Internationalization using MessageSource所示,主要作用就是使用国际化,定制不同的消息。
需要注意的是 MessageSource 定义的 Bean 名字必须为 messageSource, 而如果找不到则会默认注册 DelegatingMessageSource 作为 messageSource 的 Bean。

使用

1. 创建国际化文件

13-Spring initMessageSource - 图2
13-Spring initMessageSource - 图3

2. 声明 MessageSource

在 JavaConfig 中 声明 MessageSource , 记得名字一定要叫做 messageSource

  1. @Configuration
  2. @ComponentScan("com.liuzhihang")
  3. public class JavaConfig {
  4. @Bean(name = "messageSource")
  5. public MessageSource getMessageSource() {
  6. ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
  7. messageSource.setDefaultEncoding("UTF-8");
  8. messageSource.addBasenames("message", "message_en");
  9. return messageSource;
  10. }
  11. }

3. 测试结果

  1. public class AnnotationConfigApplicationTest {
  2. public static void main(String[] args) {
  3. AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
  4. context.register(JavaConfig.class);
  5. context.refresh();
  6. MessageSource messageSource = context.getBean(MessageSource.class);
  7. String zhMessage = messageSource.getMessage("user.name", null, null, Locale.CHINA);
  8. String enMessage = messageSource.getMessage("user.name", null, null, Locale.ENGLISH);
  9. System.out.println("zhMessage = " + zhMessage);
  10. System.out.println("enMessage = " + enMessage);
  11. }
  12. }

如上所示,执行之后输出结果如下:
13-Spring initMessageSource - 图4
知道了国际化是如何使用的之后,再想一想这一步源码,就知道是什么作用了吧!

initMessageSource 源码

  1. protected void initMessageSource() {
  2. ConfigurableListableBeanFactory beanFactory = getBeanFactory();
  3. // Bean 的名称必须要是 messageSource
  4. if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {
  5. this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);
  6. // Make MessageSource aware of parent MessageSource.
  7. if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) {
  8. HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource;
  9. if (hms.getParentMessageSource() == null) {
  10. // Only set parent context as parent MessageSource if no parent MessageSource
  11. // registered already.
  12. hms.setParentMessageSource(getInternalParentMessageSource());
  13. }
  14. }
  15. if (logger.isTraceEnabled()) {
  16. logger.trace("Using MessageSource [" + this.messageSource + "]");
  17. }
  18. }
  19. else {
  20. // Use empty MessageSource to be able to accept getMessage calls.
  21. // 否则则使用默认的
  22. DelegatingMessageSource dms = new DelegatingMessageSource();
  23. dms.setParentMessageSource(getInternalParentMessageSource());
  24. this.messageSource = dms;
  25. beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);
  26. if (logger.isTraceEnabled()) {
  27. logger.trace("No '" + MESSAGE_SOURCE_BEAN_NAME + "' bean, using [" + this.messageSource + "]");
  28. }
  29. }
  30. }

这块源码唯一值得关注的地方就是,Bean 的名称必须要是 messageSource 。

总结

本文通过官网,了解到什么是国际化,以及国际化的使用,并结合代码和源码,知其然,知其所以然。
当然本文需要注意的地方就是国际化 MessageSource 的 Bean 名称要必须为 messageSource。
13-Spring initMessageSource - 图5

相关推荐