前言

在上个月中已经写了一篇关于国际化遇到的问题 遇到的问题以及解决方案 这篇是专注于一些优化的点,基于 SpringBoot 写一个 starter 的状态下。

添加静态方法

制作一个 spring-starter 这篇文章中,已经写好了代码如何在 SpringBoot 项目启动时去加载一个 Bean,但是这样去写,产生了一个问题,在所有的类我们必须按照以下的方式进行调用

@Resource
private InternationalService internationalService;

必须将 InternationalService 注入进来,才可以使用里面的方法,因此出现了三个问题:

  1. 每一个需要国际化的文件,最上面都需要添加如上的代码
  2. 当一些实体层需要国际化时,也需要采用上面的方式
  3. 枚举类无法使用该方法进行 直接国际化
所以我将其改为静态方法,让其直接使用 InternationalService.getMessage() 即可。

枚举类加载产生的问题

在 SpringBoot 项目启动时,虽然会按照顺序的去加载相应的 Bean,但是 枚举类 确是一个特例,枚举中的属性可能会被提前加载,但是在这个时候我的 InternationalService 还没有进行初始化操作,导致了 MessageSource 对象为 null,最后报错 NoSuchMessageException

我的解决方式也比较暴力,并没有正面的解决该问题,而是直接创建一个新的 ResourceBundleMessageSource 临时提供给 MessageSource 对象。

    public static String getMessage(String path) {
        return getMessage(path, (Object[])null);
    }

    public static String getMessage(String path, Object[] replace) {
        if (messageSource == null) {
            Class var2 = InternationalService.class;
            synchronized(InternationalService.class) {
                if (messageSource == null) {
                    messageSource = getMessageSource();
                }
            }
        }

        return messageSource.getMessage(path, replace, LocaleContextHolder.getLocale());
    }

    public static ResourceBundleMessageSource getMessageSource() {
        ResourceBundleMessageSource resourceBundleMessageSource = new ResourceBundleMessageSource();
        resourceBundleMessageSource.setDefaultEncoding("UTF-8");
        resourceBundleMessageSource.setBasenames(new String[]{"i18n/messages"});
        return resourceBundleMessageSource;
    }
最后修改:2023 年 01 月 12 日
如果觉得我的文章对你有用,请随意赞赏