我已经使用Java中的ResourceBundles实现了插件机制和语言包。
如果我想从核心程序(而不是从插件)获得ResourceBundle
,效果很好。
问题是我想增加一种可能性,可以在插件中创建ResourceBundle
,并且只能在插件中使用。
使用URLClassLoader
和Reflections
加载插件。我无法访问(我不想)翻译类中的插件ClassLoader
。
因此,程序将加载该插件并稍后在该插件内部执行一个方法(该插件不在Classpath中),然后该插件将执行translate方法。
为了对此进行归档,我想从调用方法中获取ClassLoader对象。
诸如this或this之类的方法可能有用,但是我看不到获取Class / ClassLoader的方法,而不是获取类名的方法。
我以为我可以使用Stacktrace来获取调用方法的ClassLoader,但只能使用.getClassName
来获取名称,而不能使用Class
或ClassLoader
的调用者对象。
这就是我所拥有的:
翻译
public static String translate(Locale locale,String s) {
for (ResourceBundle bundle : getResourceBundles(locale/*,Thread.currentThread().getStackTrace()[1].getClassLoader();*/)) {
try {
return bundle.getString(s);
}catch (MissingResourceException e) {
//ignore/next iteration
}
}
return s;
}
getResourceBundles
private static Set<ResourceBundle> getResourceBundles(Locale locale,ClassLoader... loaders){
Set<ResourceBundle> bundles=new HashSet<>();
bundles.add(ResourceBundle.getBundle(BASE_NAME,locale,MyClass.class.getClassLoader()));
for (ClassLoader loader : loaders) {
ResourceBundle pluginBundle=getResourceBundle(g,loader);
if (pluginBundle!=null) {
bundles.add(pluginBundle);
}
}
return bundles;
}
答案 0 :(得分:2)
我认为这种反复试验的方法不是一个好主意。都不会为每个字符串重新获取所有捆绑包。似乎该翻译服务似乎并没有增加让插件读取其捆绑包并对其调用getString
的价值,至少没有一种价值可以证明代码的开销和复杂性。 / p>
由于标准的ResourceBundle.getBundle
方法已经考虑了调用者的上下文,因此当将字段声明和获取表达式放在插件中并在其上调用getString
时,字段声明和获取表达式将是微不足道的比调用翻译服务的方法更复杂。
为了完整起见,可以从Java 9开始以标准方式获取调用者类。然后,您可以像
private static final StackWalker STACK_WALKER
= StackWalker.getInstance(StackWalker.Option.RETAIN_CLASS_REFERENCE);
public static String translate(Locale locale, String s) {
for(ResourceBundle bundle: getResourceBundles(locale,
STACK_WALKER.getCallerClass().getClassLoader())) {
try {
return bundle.getString(s);
}catch (MissingResourceException e) {
//ignore/next iteration
}
}
return s;
}