spring学习总结004 --- IOC容器启动源码(MessageSource)

ApplicationContext的refresh方法的下一个方法为:initMessageSource,用于初始化国际化信息

spring加载国际化资源文件的接口类MessageSource,spring提供了如下两个类:

org.springframework.context.support.ReloadableResourceBundleMessageSource

org.springframework.context.support.ResourceBundleMessageSource

二者的区别为国际化资源文件路径的差异:

(1)ReloadableResourceBundleMessageSource能够读取classpath下的资源文件及外部文件

(2)ResourceBundleMessageSource只能读取classpath下的资源文件

1、MessageSource接口

2、ReloadableResourceBundleMessageSource和ResourceBundleMessageSource示例

@Slf4j
public class Test1 {
    public static void main(String[] args) {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:bean1.xml");

        MessageSource messageSource1 = (MessageSource) context.getBean("messageSource1");
        log.info("Msg1:{}", messageSource1.getMessage("name", new Object[] { "bale" }, Locale.US));

        MessageSource messageSource2 = (MessageSource) context.getBean("messageSource2");
        log.info("Msg2:{}", messageSource2.getMessage("name", new Object[] { "bale" }, Locale.US));
    }
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean class="org.springframework.context.support.ReloadableResourceBundleMessageSource" id="messageSource1">
        <property name="cacheSeconds" value="5" />
        <property name="basename" value="classpath:/i18n/messages" />
    </bean>

    <bean class="org.springframework.context.support.ResourceBundleMessageSource" id="messageSource2">
        <property name="basename" value="i18n/messages" />
        <property name="cacheSeconds" value="5" />
    </bean>

</beans>

运行结果:

3、initMessageSource流程

protected void initMessageSource() {
   //获取Bean工厂,一般是DefaultListBeanFactory
   ConfigurableListableBeanFactory beanFactory = getBeanFactory();
   //首先判断是否已有xml文件定义了id为messageSource的bean对象
   if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {
      //如果有,则从Bean工厂得到这个bean对象
      this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);
      //当父类context不为空,并且这个bean对象是HierarchicalMessageSource类型
      if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) {
         //为HierarchicalMessageSource的实现类
         HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource;
         //设置父类MessageSource,此处设置内部的parent messageSource
         if (hms.getParentMessageSource() == null) {
            hms.setParentMessageSource(getInternalParentMessageSource());
         }
      }
   }
   else {
      //如果没有xml文件定义信息源对象,新建DelegatingMessageSource类作为messageSource的Bean
      //因为DelegatingMessageSource类实现了HierarchicalMessageSource接口,而这个接口继承了MessageSource这个类
      //因此实现了这个接口的类,都是MessageSource的子类,因此DelegatingMessageSource也是一个MessageSource
      DelegatingMessageSource dms = new DelegatingMessageSource();
      //给这个DelegatingMessageSource添加父类消息源
      dms.setParentMessageSource(getInternalParentMessageSource());
      this.messageSource = dms;
      //将这个messageSource实例注册到Bean工厂中
      beanFactory.registerSingleton(MESSAGE_SOURCE_BEAN_NAME, this.messageSource);
   }
}
原文地址:https://www.cnblogs.com/sniffs/p/13257406.html