2011-06-05 22 views
14

可以這樣做嗎?目前它是這樣做的:通過Spring Framework中的註釋獲取來自resourceBundle的本地化消息

<bean id="resource" class="org.springframework.context.support.ResourceBundleMessageSource"> 
    <property name="basenames"> 
     <list> 
      <value>content.Language</value> 
     </list> 
    </property> 
</bean> 

@Autowired 
protected MessageSource resource; 

protected String getMessage(String code, Object[] object, Locale locale) { 
    return resource.getMessage(code, object, locale); 
} 

有沒有辦法讓它像通過@Value註解獲取屬性?

<util:properties id="generals" location="classpath:portlet.properties" /> 

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

因爲不必調用該方法通常是好的,但例如當單元測試,這是痛苦......那麼在某些情況下,的webdriver的PageObject模式,其中對象沒有任何初始化,這將是非常有幫助的

+0

我也想知道爲什麼這個功能不存在,在3.1和可能3。2沒有這樣的歌曲要實施。 – lisak 2011-06-05 23:54:36

+0

Is:supported.lang.codes屬性文件的鍵值對,還是應該是程序計算所有支持的語言的值? – Ralph 2011-06-06 10:24:35

+0

這只是屬性文件的一個關鍵值。這實際上是獲取屬性的非常方便的方式。我希望Spring能夠像本地化一樣... @Localize(「#{langCode ['some.error.message]}」) – lisak 2011-06-06 10:28:12

回答

4

問題是,這隻對單元測試非常有用。在實際應用程序中,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; 
    } 
25

我相信你混合兩個概念:

  • 屬性文件
  • 消息資源包

屬性文件包含屬性(獨立於區域)。在春季,它們可以通過例如util:properties加載並且可以在@Value註釋中使用。

但是消息資源包(基於類似屬性文件的文件)是語言依賴。在春季,您可以通過org.springframework.context.support.ResourceBundleMessageSource加載它們。但不通過@Value注入字符串。你不能注射它們,因爲@Value注射是每個豆子完成一次,@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); 
    }  
} 

爲了讓它運行,您需要啓用<context:spring-configured />打開的AspectJ @Configurable支持,並且(這是importent),您需要在相同的應用程序上下文中實例化Ressouce Bundle消息源(例如,在Web應用程序中,您在大多數情況下將ReloadableResourceBundleMessageSource定義置於Web應用程序上下文中,但這不起作用這個c因爲MSG對象處於「正常」應用程序上下文中。

+0

Ralph,我沒有混淆任何東西,我使用了兩個3年。我剛纔說過,如果Spring有它,單元測試會很方便。我是這麼做的,因爲Edgar說,我使用BeanPostProcessor來填充ResourceBundle註釋的字段。我認爲這比在這種情況下使用@Value註解更好。但是,非常感謝您展示這個@Value註釋的用例,我不知道我能做到這一點。 – lisak 2011-06-06 11:49:32

+0

Ou我看到了,你被「via @Value annotation」弄糊塗了我並不是故意使用@Value註釋本身,我的意思是「通過註釋」 – lisak 2011-06-06 11:53:31

相關問題