014 国际化

一. 概述

  在ApplicaitonContext之中,我们 介绍过ApplicationContext实现了MessageSource接口,也就是说我们使用的IOC容器也是具有国际化的功能.

    我们看一下IOC创建的流程代码.

    postProcessBeanFactory(beanFactory);

                // Invoke factory processors registered as beans in the context.
                invokeBeanFactoryPostProcessors(beanFactory);

                // Register bean processors that intercept bean creation.
                registerBeanPostProcessors(beanFactory);

                // Initialize message source for this context.
                initMessageSource();

                // Initialize event multicaster for this context.
                initApplicationEventMulticaster();

                // Initialize other special beans in specific context subclasses.
                onRefresh();

                // Check for listener beans and register them.
                registerListeners();

                // Instantiate all remaining (non-lazy-init) singletons.
                finishBeanFactoryInitialization(beanFactory);

                // Last step: publish corresponding event.
                finishRefresh();

我们看到了在IOC容器创建的过程中有一步就是初始化国际信息.

我们进入看一下:

protected void initMessageSource() {
        ConfigurableListableBeanFactory beanFactory = getBeanFactory();
        if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {
            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.isDebugEnabled()) {
                logger.debug("Using MessageSource [" + this.messageSource + "]");
            }
        }
        else {
            // Use empty MessageSource to be able to accept getMessage calls.
            DelegatingMessageSource dms = new DelegatingMessageSource();
            dms.setParentMessageSource(getInternalParentMessageSource());
            this.messageSource = dms;
            beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);
            if (logger.isDebugEnabled()) {
                logger.debug("Unable to locate MessageSource with name '" + MESSAGE_SOURCE_BEAN_NAME +
                        "': using default [" + this.messageSource + "]");
            }
        }
    }

上面的代码描述了如果IOC容器之中有一个名字为messageSource的Bean,类型为MessageSource,就使用它作为国际化文件的方式.

如果不存在,就使用一个委托的代理对象完成.

  这也就是说,我们可以在IOC容器之中定义一个MessageSource的子类,实现国际化.


二 .MessageSosource接口

public interface MessageSource {

    String getMessage(String code, Object[] args, String defaultMessage, Locale locale);
   
    String getMessage(String code, Object[] args, Locale locale) throws NoSuchMessageException;
   
    String getMessage(MessageSourceResolvable resolvable, Locale locale) throws NoSuchMessageException;

}

接口之中定义了通过键获取值的方式,同时可以提供参数完成占位符的替换功能.

  现在我们需要寻找一个MessageSource的实现类.一般情况下我们喜欢使用ResourceBundleMessageSource这个实现类.


三.演示一下国际化

首先我们配置一个国际化文件:在classpath之下定义一个i18n_zh_CN.properties.

trek.name={0}haoren

配置ResourceBundleMessageSource的实现类.

    <bean id="messageSource" class="org.springframework.context.support.ResourceBundleMessageSource">
        <property name="basenames">
            <list>
                <value>i18n</value>
            </list>
        </property>
    </bean>

测试代码:  

ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
        System.out.println(context.getMessage("trek.name", new Object[] {"trek"}, Locale.getDefault()));

  

猜你喜欢

转载自www.cnblogs.com/trekxu/p/9092136.html
014