Spring MessageSource

初始化入口

  • org.springframework.context.support.AbstractApplicationContext.refresh方法有initMessageSource()方法进行了MessageSource初始化
  1. protected void initMessageSource() {
  2. ConfigurableListableBeanFactory beanFactory = getBeanFactory();
  3. // 判断是否含有 messageSource
  4. if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {
  5. // 读取xml配置文件中 id="messageSource"的数据
  6. this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);
  7. // Make MessageSource aware of parent MessageSource.
  8. if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) {
  9. HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource;
  10. if (hms.getParentMessageSource() == null) {
  11. // Only set parent context as parent MessageSource if no parent MessageSource
  12. // registered already.
  13. hms.setParentMessageSource(getInternalParentMessageSource());
  14. }
  15. }
  16. if (logger.isTraceEnabled()) {
  17. logger.trace("Using MessageSource [" + this.messageSource + "]");
  18. }
  19. }
  20. else {
  21. // Use empty MessageSource to be able to accept getMessage calls.
  22. // 没有使用默认的 DelegatingMessageSource
  23. DelegatingMessageSource dms = new DelegatingMessageSource();
  24. dms.setParentMessageSource(getInternalParentMessageSource());
  25. this.messageSource = dms;
  26. // 注册单例对象
  27. beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);
  28. if (logger.isTraceEnabled()) {
  29. logger.trace("No '" + MESSAGE_SOURCE_BEAN_NAME + "' bean, using [" + this.messageSource + "]");
  30. }
  31. }
  32. }

读取 xml 配置文件

image-20200119141937915

getMessage

  • org.springframework.context.support.AbstractApplicationContext#getMessage(java.lang.String, java.lang.Object[], java.util.Locale)
  1. @Override
  2. public String getMessage(String code, @Nullable Object[] args, Locale locale) throws NoSuchMessageException {
  3. return getMessageSource().getMessage(code, args, locale);
  4. }
  • org.springframework.context.support.AbstractMessageSource#getMessage(java.lang.String, java.lang.Object[], java.util.Locale)

    1. @Override
    2. public final String getMessage(String code, @Nullable Object[] args, Locale locale) throws NoSuchMessageException {
    3. // 获取对应的信息
    4. String msg = getMessageInternal(code, args, locale);
    5. if (msg != null) {
    6. return msg;
    7. }
    8. // 默认信息 null
    9. String fallback = getDefaultMessage(code);
    10. if (fallback != null) {
    11. return fallback;
    12. }
    13. throw new NoSuchMessageException(code, locale);
    14. }
    • 两个方法

      1. org.springframework.context.support.AbstractMessageSource#getDefaultMessage(java.lang.String)

        1. @Nullable
        2. protected String getDefaultMessage(String code) {
        3. // 判断是否使用默认值
        4. if (isUseCodeAsDefaultMessage()) {
        5. return code;
        6. }
        7. return null;
        8. }
        • 返回 code 本身或者null
      2. org.springframework.context.support.AbstractMessageSource#getMessageInternal

        1. @Nullable
        2. protected String getMessageInternal(@Nullable String code, @Nullable Object[] args, @Nullable Locale locale) {
        3. if (code == null) {
        4. return null;
        5. }
        6. if (locale == null) {
        7. // 获取语言默认值
        8. locale = Locale.getDefault();
        9. }
        10. Object[] argsToUse = args;
        11. if (!isAlwaysUseMessageFormat() && ObjectUtils.isEmpty(args)) {
        12. // Optimized resolution: no arguments to apply,
        13. // therefore no MessageFormat needs to be involved.
        14. // Note that the default implementation still uses MessageFormat;
        15. // this can be overridden in specific subclasses.
        16. String message = resolveCodeWithoutArguments(code, locale);
        17. if (message != null) {
        18. return message;
        19. }
        20. }
        21. else {
        22. // Resolve arguments eagerly, for the case where the message
        23. // is defined in a parent MessageSource but resolvable arguments
        24. // are defined in the child MessageSource.
        25. argsToUse = resolveArguments(args, locale);
        26. MessageFormat messageFormat = resolveCode(code, locale);
        27. if (messageFormat != null) {
        28. synchronized (messageFormat) {
        29. return messageFormat.format(argsToUse);
        30. }
        31. }
        32. }
        33. // Check locale-independent common messages for the given message code.
        34. Properties commonMessages = getCommonMessages();
        35. if (commonMessages != null) {
        36. String commonMessage = commonMessages.getProperty(code);
        37. if (commonMessage != null) {
        38. return formatMessage(commonMessage, args, locale);
        39. }
        40. }
        41. // Not found -> check parent, if any.
        42. return getMessageFromParent(code, argsToUse, locale);
        43. }
  • org.springframework.context.support.ResourceBundleMessageSource#resolveCodeWithoutArguments

    1. @Override
    2. protected String resolveCodeWithoutArguments(String code, Locale locale) {
    3. Set<String> basenames = getBasenameSet();
    4. for (String basename : basenames) {
    5. // 加载 basename
    6. ResourceBundle bundle = getResourceBundle(basename, locale);
    7. if (bundle != null) {
    8. // 从basename对应的文件中获取对应的值
    9. String result = getStringOrNull(bundle, code);
    10. if (result != null) {
    11. return result;
    12. }
    13. }
    14. }
    15. return null;
    16. }

image-20200119143046066

  • 加载后截图

    获取方法String result = getStringOrNull(bundle, code);就是 map 获取

image-20200119144019171

  • 没有配置文件的情况

    image-20200119145138205