openmeetings-install分析(六)——ImportInitvalues类分析(4)

2021SC@SDUSC


openmeetings-install分析(五)中,我们已经分析了关键方法loadAll()中的loadInitUserAndGroup方法和loadDefaultRooms方法的一部分,在这篇文章中,我们来把loadDefaultRooms方法剩下的内容分析完,再对ImportInitvalues类进行一个小总结


上一篇我们分析到了下面这句代码:

String value = l.getStringIgnoreSettings(key, null, null, loc, null, “[Missing]”);

    // org\apache\wicket\Localizer.class
    public String getStringIgnoreSettings(String key, Component component, IModel<?> model, Locale locale, String style, String defaultValue) {
        boolean addedToPage = false;
        if (component != null) {
            if (component instanceof Page || null != component.findParent(Page.class)) {
                addedToPage = true;
            }

            if (!addedToPage && log.isWarnEnabled()) {
                log.warn("Tried to retrieve a localized string for a component that has not yet been added to the page. This can sometimes lead to an invalid or no localized resource returned. Make sure you are not calling Component#getString() inside your Component's constructor. Offending component: {}", component);
            }
        }

        String cacheKey = null;
        // 我们传入的component是null,所以这里variation的赋值为null
        String variation = component != null ? component.getVariation() : null;
        if (locale == null && component != null) {
            locale = component.getLocale();
        }

        if (locale == null) {
            locale = Session.exists() ? Session.get().getLocale() : Locale.getDefault();
        }

        if (style == null && component != null) {
            style = component.getStyle();
        }

        // 这里我们传入的style=null,需要从Session中获取style
        if (style == null) {
            style = Session.exists() ? Session.get().getStyle() : null;
        }
        
        // 满足if条件
        if (this.cache != null && (component == null || addedToPage)) {
            // 会返回“key + '-' + locale.toString() + '-' + style”
            cacheKey = this.getCacheKey(key, component, locale, style, variation);
        }

        String value;
        if (cacheKey != null && this.cache.containsKey(cacheKey)) {
            // 如果cache里包含该cacheKey的话,就取出它的value值,这里的cache是ConcurrentHashMap表,在该类一开始即定义了
            value = this.getFromCache(cacheKey);
            if (log.isDebugEnabled()) {
                log.debug("Property found in cache: '" + key + "'; Component: '" + (component != null ? component.toString(false) : null) + "'; value: '" + value + '\'');
            }
        } else {
            if (log.isDebugEnabled()) {
                log.debug("Locate property: key: '" + key + "'; Component: '" + (component != null ? component.toString(false) : null) + '\'');
            }

            Iterator<IStringResourceLoader> iter = this.getStringResourceLoaders().iterator();

            IStringResourceLoader loader;
            for(value = null; iter.hasNext() && value == null; value = loader.loadStringResource(component, key, locale, style, variation)) {
                loader = (IStringResourceLoader)iter.next();
            }

            if (cacheKey != null) {
                this.putIntoCache(cacheKey, value);
            }

            if (value == null && log.isDebugEnabled()) {
                log.debug("Property not found; key: '" + key + "'; Component: '" + (component != null ? component.toString(false) : null) + '\'');
            }
        }

        if (value == null) {
            value = defaultValue;
        }

        return value != null ? this.substitutePropertyExpressions(component, value, model) : null;
    }

分析一下这个方法中的这段代码:

            Iterator<IStringResourceLoader> iter = this.getStringResourceLoaders().iterator();
            IStringResourceLoader loader;
        for(value = null; iter.hasNext() && value == null; value = loader.loadStringResource(component, key, locale, style, variation)) {
            loader = (IStringResourceLoader)iter.next();
        }

IStringResourceLoader 是一个字符串资源加载器接口,允许将策略模式应用于应用程序的资源字符串加载。

getStringResourceLoaders方法会通过Application对象得到ResourceSettings对象,这个对象用于获取与资源相关的设置,然后再调用这个对象的getStringResourceLoaders方法得到一个包含了实现IStringResourceLoader接口的对象列表,如下面代码:

private final List<IStringResourceLoader> stringResourceLoaders = Generics.newArrayList(6);

Generics是wicket中的一个泛型类
openmeetings-install分析(六)——ImportInitvalues类分析(4)
返回一个指定容量的列表,列表里的数据类型是T(即Type(Java 类)),在我们的代码中它会返回一个容量为6的列表,最后第一句代码得到的是一个对实现了IStringResourceLoader接口的对象列表的迭代器

            for(value = null; iter.hasNext() && value == null; value = loader.loadStringResource(component, key, locale, style, variation)) {
                loader = (IStringResourceLoader)iter.next();
            }

这段代码利用迭代器遍历了列表
openmeetings-install分析(六)——ImportInitvalues类分析(4)
这个方法用于根据给定组件、资源键、语言环境和样式组合获取相应的字符串资源,然后将其赋给value,当value!=null或者已经遍历完时,循环结束

 return value != null ? this.substitutePropertyExpressions(component, value, model) : null;

最后返回的结果:如果value==null,就返回null;否则,调用substitutePropertyExpressions方法,这里我们传入的component和model都是null,根据substitutePropertyExpressions方法,我们会将value值原样返回

因为有一些参数我们不知道它是否已经赋值,所以在分析方法时不能确定走的是哪个条件语句,所以这里我们只是把能分析到的分析了一下,至于程序具体是怎么走的,短时间内可能无法很好地了解清楚…

我们再回到Application类的getString方法中

	// Application.java
	public static String getString(String key, final Locale loc, String... _params) {
		if (!exists()) {
			ThreadContext.setApplication(org.apache.wicket.Application.get(appName));
		}
		String[] params = _params;
		if ((params == null || params.length == 0) && STRINGS_WITH_APP.contains(key)) {
			params = new String[]{getApplicationName()};
		}
		Localizer l = get().getResourceSettings().getLocalizer();
		String value = l.getStringIgnoreSettings(key, null, null, loc, null, "[Missing]");
		if (params != null && params.length > 0) {
		    // 为指定的语言环境和模式构造MessageFormat
			final MessageFormat format = new MessageFormat(value, loc);
			value = format.format(params);
		}
		// 如果该应用的配置类型为开发模式
		if (RuntimeConfigurationType.DEVELOPMENT == get().getConfigurationType()) {
		    // 格式化后的字符串即“[key]”
			value += String.format(" [%s]", key);
		}
		return value;
	}

下面我们分析这段代码:

if (params != null && params.length > 0) {
		    // 为指定的语言环境和模式构造MessageFormat
			final MessageFormat format = new MessageFormat(value, loc);
			value = format.format(params);
		}

MessageFormat提供了一种以与语言无关的方式生成连接消息的方法。使用此函数构造显示给最终用户的消息。MessageFormat接受一组对象,格式化它们,然后将格式化的字符串插入到模式的适当位置。在这里是根据value模式和loc语言取得MessageFormat对象,再利用该对象的format方法对参数列表params格式化


至此,结合上篇文章的内容,我们就分析完了LabelDao.getString方法,也就分析完了loadDefaultRooms方法,也就分析完了loadAll方法,也就分析完了整个ImportInitvalues类,我们下面稍微总结一下这个类

ImportInitvalues类总结

1. 入口:loadAll()等

同包下的cli文件夹下的Admin类会调用ImportInitvalues类的loadAll、loadSystem等方法,开始对变量进行初始化
openmeetings-install分析(六)——ImportInitvalues类分析(4)

2. loadAll步骤

openmeetings-install分析(六)——ImportInitvalues类分析(4)

ImportInitvalues类分析整理

openmeetings-install分析(二)——ImportInitvalues类分析(1)
openmeetings-install分析(三)——ImportInitvalues类分析(2)
openmeetings-install分析(五)——ImportInitvalues类分析(3)
openmeetings-install分析(六)——ImportInitvalues类分析(4)

上一篇:moment.js 封装时间格式化方法


下一篇:11.11 C#