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中的一个泛型类
返回一个指定容量的列表,列表里的数据类型是T(即Type(Java 类)),在我们的代码中它会返回一个容量为6的列表,最后第一句代码得到的是一个对实现了IStringResourceLoader接口的对象列表的迭代器
for(value = null; iter.hasNext() && value == null; value = loader.loadStringResource(component, key, locale, style, variation)) {
loader = (IStringResourceLoader)iter.next();
}
这段代码利用迭代器遍历了列表
这个方法用于根据给定组件、资源键、语言环境和样式组合获取相应的字符串资源,然后将其赋给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等方法,开始对变量进行初始化
2. loadAll步骤
ImportInitvalues类分析整理
openmeetings-install分析(二)——ImportInitvalues类分析(1)
openmeetings-install分析(三)——ImportInitvalues类分析(2)
openmeetings-install分析(五)——ImportInitvalues类分析(3)
openmeetings-install分析(六)——ImportInitvalues类分析(4)