Spring MessageSource详解

简介: 《基础系列》

初始化入口

  • 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 配置文件

1.png

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
  1. 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

2.png

  • 加载后截图
    获取方法String result = getStringOrNull(bundle, code);就是 map 获取

4.png

  • 没有配置文件的情况
  • 5.png
相关文章
|
Java 测试技术 Spring
Spring-国际化信息02-MessageSource接口
Spring-国际化信息02-MessageSource接口
133 0
|
XML 存储 缓存
从MessageSource源码出发实战spring·i18n国际化的三种改造方案
从源码去看MessageSource的几个实现类的源码出发,基于spring的国际化支持,实现国际化的开箱即用,静态文件配置刷新生效以及全局异常国际化处理。
578 0
从MessageSource源码出发实战spring·i18n国际化的三种改造方案
|
自然语言处理 Java 开发者
Spring 源码阅读 15:初始化 MessageSource
本文分析 Spring 上下文初始化过程中, MessageSource 初始化的过程。MessageSource 是 Spring 框架中,处理 i18n 的组件。
277 0
Spring 源码阅读 15:初始化 MessageSource
|
Java Spring 容器
Spring 国际化支持之 MessageSource
背景 为了友好的支持各个国家的语言,Java 本身已经提供了对国际化的支持,上篇文章《Java 国际化与文本格式化》已经介绍了 Java 对国际化的支持。
294 0
|
缓存 Java 测试技术
Spring(21)——国际化MessageSource
21 国际化MessageSource Spring中定义了一个MessageSource接口,以用于支持信息的国际化和包含参数的信息的替换。MessageSource接口的定义如下,对应的方法说明已经在方法上注释了。
1146 0
|
Java Spring 安全
Spring的国际化资源messageSource
Spring中可以使用两个类加载资源文件:ReloadableResourceBundleMessageSource和ResourceBundleMessageSource。 可配置如下messageSource这个bean id不能变: @Bean public MessageS...
1337 0
|
Java 测试技术 Spring
Spring messageSource
Spring中可以使用两个类加载资源文件: org.springframework.context.support.ReloadableResourceBundleMessageSource 和 org.
1016 0
|
1月前
|
存储 JSON Java
SpringBoot集成AOP实现每个接口请求参数和返回参数并记录每个接口请求时间
SpringBoot集成AOP实现每个接口请求参数和返回参数并记录每个接口请求时间
69 2
|
1月前
|
前端开发 Java 应用服务中间件
Springboot对MVC、tomcat扩展配置
Springboot对MVC、tomcat扩展配置
|
16小时前
|
Java Maven
springboot项目打jar包后,如何部署到服务器
springboot项目打jar包后,如何部署到服务器
7 1