ioc源码分析(七)----refresh之initMessageSource方法

这个我也没用过,先记录下来,用的时候再说。。。。

spring中初始化MessageSource组件

    /**
     * 初始化此上下文的消息源。
     * 如果没有在此上下文中定义,请使用父级。
     */
    protected void initMessageSource() {
        //获取工厂
        ConfigurableListableBeanFactory beanFactory = getBeanFactory();
        //先找工厂中messageSource是否有对应的实例(注册过)
        if (beanFactory.containsLocalBean(MESSAGE_SOURCE_BEAN_NAME)) {
            this.messageSource = beanFactory.getBean(MESSAGE_SOURCE_BEAN_NAME, MessageSource.class);
            //messageSource是否有父消息源
            if (this.parent != null && this.messageSource instanceof HierarchicalMessageSource) {
                HierarchicalMessageSource hms = (HierarchicalMessageSource) this.messageSource;
                if (hms.getParentMessageSource() == null) {
                    // 父MessageSource未注册,则设置messageSource的parentMessageSource为“父上下文的‘MessageSource’ ”。
                    hms.setParentMessageSource(getInternalParentMessageSource());
                }
            }
            if (logger.isDebugEnabled()) {
                logger.debug("Using MessageSource [" + this.messageSource + "]");
            }
        }
        else {//没有对应的实例,则自己初始化一个
            // 实例化一个spring默认实现消息源对象
            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 + "]");
            }
        }
    }

 //获取父上下文的消息源
    protected MessageSource getInternalParentMessageSource()
     {
        return (getParent() instanceof AbstractApplicationContext) ?
            ((AbstractApplicationContext) getParent()).messageSource : getParent();
    }

MessageSource架构图

在这里插入图片描述

  1. MessageSource:抽象化的消息接口
  2. HierarchicalMessageSource:分层的消息源接口,可获取父消息源
  3. MessageSourceSupport:帮助消息源解析的抽象类,通过指定“消息格式化组件MessageFormat”格式化消息。
  4. DelegatingMessageSource: 消息源解析委派类(用户未指定时,SpringContext默认使用当前类),功能比较简单:将字符串和参数数组格式化为一个消息字符串
  5. AbstractMessageSource:支持‘配置文件’的方式国际化资源 的 抽象类,内部提供一个与区域设置无关的公共消息配置文件,消息代码为关键字。
  6. StaticMessageSource:主要用于程序测试,它允许通过编程的方式提供国际化信息
  7. ResourceBundleMessageSource:该实现类允许用户通过beanName指定一个资源名(包括类路径的全限定资源名),或通过beanNames指定一组资源名。不同的区域获取加载资源文件,达到国际化信息的目的。
  8. ReloadableResourceBundleMessageSource:同ResourceBundleMessageSource区别(spring3.2):
    1)加载资源类型及方式:
    ResourceBundleMessageSource 依托JDK自带ResourceBundle加载资源,支持绝对路径和工程路径,支持文件为.class文件和.properties。
    ReloadResourceBundleMessageSource依托spring的ResourceLoader加载Resource资源,功能更加强大,同时支持.properties和.xml文件。
    2)缓存时间:
    ResourceBundleMessageSource主要利用ResourceBundle.Control 实现简单的自动重载。
    ReloadResourceBundleMessageSource每次加载资源都会记录每个资源的加载时间点,在缓存资源过期后会再次比较文件的修改时间,如果不变则不需要重新加载,同时刷新本次加载时间点。
    3)编码方式:
    ResourceBundleMessageSource可以统一指定默认的文件编码方式 。
    ReloadResourceBundleMessageSource不仅可以指定统一的默认编码方式,也同时支持为每个文件单独制定编码方式。

1. MessageSource(接口)

public interface MessageSource {
    /**
     * 尝试解决消息。 如果没有找到消息,返回默认消息。
     */
    String getMessage(String code, Object[] args, String defaultMessage, Locale locale);
    
    /**
     * 尝试解决消息。 如果无法找到消息,则视为错误。
     */
    String getMessage(String code, Object[] args, Locale locale) throws NoSuchMessageException;
    
    /**
     * 尝试使用传入的{@code MessageSourceResolvable}参数中包含的所有属性来解析消息。
     * <p>NOTE: 我们必须在此方法上抛出{@code NoSuchMessageException},因为在调用此方法时,我们无法确定可解析的{@code defaultMessage}属性是否为空。
     */
    String getMessage(MessageSourceResolvable resolvable, Locale locale) throws NoSuchMessageException;
}

2. MessageSourceResolvable解析消息要素的包装接口和类



//解析消息要素的包装类:code、Arguments、默认消息

public interface MessageSourceResolvable {

/**    
* 返回用于解决此消息的代码,按照他们应该尝试的顺序。
因此,最后一个代码将是默认代码。   
* @return a String array of codes which are associated with this message    
*/  
String[] getCodes();
   
/**    
* 返回要用于解析此消息的参数数组。    
* @return an array of objects to be used as parameters to replace    
* placeholders within the message text    
* @see java.text.MessageFormat    
*/ 
Object[] getArguments();

   
/**  
* 返回要用于解析此消息的默认消息。    
* @return the default message, or {@code null} if no default    
*/   
String getDefaultMessage();
}

//spring默认实现的 解析消息要素的包装类
public class DefaultMessageSourceResolvable implements MessageSourceResolvable, Serializable {

   
private final String[] codes;

private final Object[] arguments;

   
private final String defaultMessage;

   
//构造方法
public DefaultMessageSourceResolvable(String code) {
      this(new String[] {code}, null, null);
    }

   
//构造方法   
public DefaultMessageSourceResolvable(String[] codes) {       
		this(codes, null, null);
    }

   
//构造方法   
public DefaultMessageSourceResolvable(String[] codes, String defaultMessage) {       
		this(codes, null, defaultMessage);
    }

   
//构造方法
 public DefaultMessageSourceResolvable(String[] codes, Object[] arguments) {        
		this(codes, arguments, null);

    }

   
//构造方法
public DefaultMessageSourceResolvable(String[] codes, Object[] arguments, String defaultMessage) {
       	
	this.codes = codes;       
	this.arguments = arguments;       
	this.defaultMessage = defaultMessage;

    }

   
//构造方法   
public DefaultMessageSourceResolvable(MessageSourceResolvable resolvable) {

      	this(resolvable.getCodes(), resolvable.getArguments(), resolvable.getDefaultMessage());

  }

   
public String[] getCodes() {
       	return this.codes;

    }

   
/**    
* 返回此可解析的默认代码,即代码数组中的最后一个代码。    
*/

   
public String getCode() {       
	return (this.codes != null && this.codes.length > 0) ? this.codes[this.codes.length - 1] : null;
    }

   
public Object[] getArguments() {       
	return this.arguments;
    }

   
public String getDefaultMessage() {      
	return this.defaultMessage;
    }

   
/**    
* 为此MessageSourceResolvable构建默认的String表示形式:包括代码,参数和默认消息。    
*/   
protected final String resolvableToString() {       
	StringBuilder result = new StringBuilder();       
	result.append("codes [").append(StringUtils.arrayToDelimitedString(this.codes,",");
       result.append("]; arguments [" +StringUtils.arrayToDelimitedString(this.arguments, ","));       
	result.append("]; default message[").append(this.defaultMessage).append(']');       
	return result.toString();
    }

  /**默认实现公开了此MessageSourceResolvable的属性。要在更具体的子类中被覆盖,可能通过{@code resolvableToString()}包含可解析的内容。    
* @see #resolvableToString()   
*/   
@Override   
public String toString() {       
	return getClass().getName() + ": " + resolvableToString();
    }

   
@Override   
public boolean equals(Object other) {       
	if (this == other) {          return true;       }       
	
	if (!(other instanceof MessageSourceResolvable)) {           return false;   }
	       
	MessageSourceResolvable otherResolvable = (MessageSourceResolvable)other;
       
	return ObjectUtils.nullSafeEquals(getCodes(),
	otherResolvable.getCodes()) &&ObjectUtils.nullSafeEquals(getArguments(),
	otherResolvable.getArguments()) && ObjectUtils.nullSafeEquals(getDefaultMessage(),
	otherResolvable.getDefaultMessage());
    }

   
@Override   
public int hashCode() {       
	int hashCode = ObjectUtils.nullSafeHashCode(getCodes());       
	hashCode = 29 * hashCode + ObjectUtils.nullSafeHashCode(getArguments());       
	hashCode = 29 * hashCode +
	ObjectUtils.nullSafeHashCode(getDefaultMessage());
	return hashCode;	
	    }

}

HierarchicalMessageSource消息源分层接口

MessageSourceSupport

DelegatingMessageSource消息源解析委派类

AbstractMessageSource抽象类

StaticMessageSource

ResourceBundleMessageSource

ReloadableResourceBundleMessageSource

MessageFormat 消息格式化组件

这个类的功能比较强大,主要就是将消息串、参数数组格式化成字符串。例如:“{0}去上学”和参数“小明”,格式化成:“小明去上学”!

//’消息格式化组件‘
public class MessageFormat extends Format {
    private static final long serialVersionUID = 6479157306784022952L;
    private int maxOffset = -1;
    //构造方法
    public MessageFormat(String pattern) {
        this.locale = Locale.getDefault(Locale.Category.FORMAT);
        applyPattern(pattern);
    }
    //构造方法
    public MessageFormat(String pattern, Locale locale) {
        this.locale = locale;
        applyPattern(pattern);
    }
    //消息区域设置
    public void setLocale(Locale locale) {
        this.locale = locale;
    }
    //获取消息区域
    public Locale getLocale() {
        return locale;
    }
    //格式化
    public final String format (Object obj) {
        return format(obj, new StringBuffer(), new FieldPosition(0)).toString();
    }
    public final StringBuffer format(Object arguments, StringBuffer result,
                                     FieldPosition pos)
    {
        return subformat((Object[]) arguments, result, pos, null);
    }
    //======省略很多代码^_^========/
}

发布了45 篇原创文章 · 获赞 3 · 访问量 2310

猜你喜欢

转载自blog.csdn.net/weixin_44046437/article/details/100007092