Spring MessageSource详解

举报
龙哥手记 发表于 2022/11/21 23:11:41 2022/11/21
1.2k+ 0 0
【摘要】 《读尽源码 第二十九篇》

初始化入口

  • org.springframework.context.support.AbstractApplicationContext.refresh方法有initMessageSource()方法进行了MessageSource初始化
    protected void initMessageSource() {
        ConfigurableListableBeanFactory beanFactory = getBeanFactory();
        // 判断是否含有 messageSource
        if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {
            // 读取xml配置文件中 id="messageSource"的数据
            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;
            // 注册单例对象
            beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);
            if (logger.isTraceEnabled()) {
                logger.trace("No '" + MESSAGE_SOURCE_BEAN_NAME + "' bean, using [" + this.messageSource + "]");
            }
        }
    }
Copy to clipboardErrorCopied

读取 xml 配置文件

image-20200119141937915

getMessage

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

        @Override
        public final String getMessage(String code, @Nullable Object[] args, Locale locale) throws NoSuchMessageException {
            // 获取对应的信息
            String msg = getMessageInternal(code, args, locale);
            if (msg != null) {
                return msg;
            }
            // 默认信息 null
            String fallback = getDefaultMessage(code);
            if (fallback != null) {
                return fallback;
            }
            throw new NoSuchMessageException(code, locale);
        }
    Copy to clipboardErrorCopied
    • 两个方法

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

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

            @Nullable
            protected String getMessageInternal(@Nullable String code, @Nullable Object[] args, @Nullable Locale locale) {
                if (code == null) {
                    return null;
                }
                if (locale == null) {
                    // 获取语言默认值
                    locale = Locale.getDefault();
                }
                Object[] argsToUse = args;
        
                if (!isAlwaysUseMessageFormat() && ObjectUtils.isEmpty(args)) {
                    // Optimized resolution: no arguments to apply,
                    // therefore no MessageFormat needs to be involved.
                    // Note that the default implementation still uses MessageFormat;
                    // this can be overridden in specific subclasses.
                    String message = resolveCodeWithoutArguments(code, locale);
                    if (message != null) {
                        return message;
                    }
                }
        
                else {
                    // Resolve arguments eagerly, for the case where the message
                    // is defined in a parent MessageSource but resolvable arguments
                    // are defined in the child MessageSource.
                    argsToUse = resolveArguments(args, locale);
        
                    MessageFormat messageFormat = resolveCode(code, locale);
                    if (messageFormat != null) {
                        synchronized (messageFormat) {
                            return messageFormat.format(argsToUse);
                        }
                    }
                }
        
                // Check locale-independent common messages for the given message code.
                Properties commonMessages = getCommonMessages();
                if (commonMessages != null) {
                    String commonMessage = commonMessages.getProperty(code);
                    if (commonMessage != null) {
                        return formatMessage(commonMessage, args, locale);
                    }
                }
        
                // Not found -> check parent, if any.
                return getMessageFromParent(code, argsToUse, locale);
            }
        Copy to clipboardErrorCopied
  • org.springframework.context.support.ResourceBundleMessageSource#resolveCodeWithoutArguments

        @Override
        protected String resolveCodeWithoutArguments(String code, Locale locale) {
            Set<String> basenames = getBasenameSet();
            for (String basename : basenames) {
                // 加载 basename
                ResourceBundle bundle = getResourceBundle(basename, locale);
                if (bundle != null) {
                    // 从basename对应的文件中获取对应的值
                    String result = getStringOrNull(bundle, code);
                    if (result != null) {
                        return result;
                    }
                }
            }
            return null;
        }
    Copy to clipboardErrorCopied

image-20200119143046066

  • 加载后截图

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

image-20200119144019171

  • 没有配置文件的情况

    image-20200119145138205

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

作者其他文章

评论(0

抱歉,系统识别当前为高风险访问,暂不支持该操作

    全部回复

    上滑加载中

    设置昵称

    在此一键设置昵称,即可参与社区互动!

    *长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

    *长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。