前言
在上个月中已经写了一篇关于国际化遇到的问题 遇到的问题以及解决方案 这篇是专注于一些优化的点,基于 SpringBoot
写一个 starter 的状态下。
添加静态方法
在 制作一个 spring-starter 这篇文章中,已经写好了代码如何在 SpringBoot 项目启动时去加载一个 Bean,但是这样去写,产生了一个问题,在所有的类我们必须按照以下的方式进行调用
@Resource
private InternationalService internationalService;
必须将 InternationalService 注入进来,才可以使用里面的方法,因此出现了三个问题:
- 每一个需要国际化的文件,最上面都需要添加如上的代码
- 当一些实体层需要国际化时,也需要采用上面的方式
- 枚举类无法使用该方法进行
直接国际化
所以我将其改为静态方法,让其直接使用 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;
}