通过Spring Framework中的注释从resourceBundle获取本地化消息

是否有可能做到这一点 ? 目前这样做是这样的:

   content.Language    @Autowired protected MessageSource resource; protected String getMessage(String code, Object[] object, Locale locale) { return resource.getMessage(code, object, locale); } 

有没有办法让它像通过@Value注释获取属性一样?

  @Value("#{generals['supported.lang.codes']}") public String langCodes; 

因为必须调用该方法通常很好,但是例如在unit testing时,这很痛苦……在某些情况下,webdriver的PageObject模式对象没有初始化,这将是非常有帮助的

我相信你混合了两个概念:

  • 属性文件
  • 消息资源包

属性文件包含属性(与语言环境无关)。 在Spring中,它们可以通过util:properties加载,并可以在@Value注释中使用。

但是消息资源包(基于看起来像属性文件的文件)是语言依赖的。 在Spring中,您可以通过org.springframework.context.support.ResourceBundleMessageSource加载它们。 但不是通过@Value注入String。 你不能注入它们,因为@Value注入每个bean完成一次, @Value将被评估一次(大多数在开始时间),并且将注入计算值。 但这不是您使用Message Resource Bundles时通常需要的。 因为每次使用变量时都需要评估值,具体取决于用户的语言。


但是你可以自己轻松地构建它!

你需要的唯一东西就是这堂课:

 import java.util.Locale; import javax.annotation.Resource; import org.springframework.beans.factory.annotation.Configurable; import org.springframework.context.MessageSource; import org.springframework.context.i18n.LocaleContextHolder; @Configurable public class MSG { private String key; @Resource(name = "messageSource") private MessageSource messageSource; public MSG(String key) { super(); this.key = key; } public String value() { Locale locale = LocaleContextHolder.getLocale(); return messageSource.getMessage(key, new Object[0], locale); } @Override public String toString() { return value(); } } 

然后你可以这样使用它:

 @Service public class Demo { @Value("demo.output.hallo") private MSG hallo; @Value("demo.output.world") private MSG world; public void demo(){ System.out.println("demo: " + hello + " " + world); } } 

要使其运行,您需要启用以启用AspectJ @Configurable支持,并且(这是重要的)您需要在同一应用程序上下文中实例化Ressouce Bundle消息源(例如在Web中)在大多数情况下,您在Web应用程序上下文中放置了ReloadableResourceBundleMessageSource定义的应用程序,但在这种情况下这不起作用,因为MSG对象位于“正常”应用程序上下文中。

关键是这对unit testing非常有用。 在实际应用程序中,Locale是一个无法在注释中硬编码的运行时信息。 区域设置基于运行时中的用户区域设置来决定。

顺便说一句,你可以自己轻松实现这一点,例如:

 @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.FIELD}) public @interface Localize { String value(); } 

 public class CustomAnnotationBeanPostProcessor implements BeanPostProcessor { public Object postProcessAfterInitialization(Object bean, String beanName) { return bean; } public Object postProcessBeforeInitialization(Object bean, String beanName) { Class clazz = bean.getClass(); do { for (Field field : clazz.getDeclaredFields()) { if (field.isAnnotationPresent(Localize.class)) { // get message from ResourceBundle and populate the field with it } } clazz = clazz.getSuperclass(); } while (clazz != null); return bean; }