从调用方获取 ClassLoader 对象

Get ClassLoader Object from Caller

我在 Java.

中使用 ResourceBundle 实现了插件机制和语言包

如果我想从核心程序(而不是插件)获取 ResourceBundle,它工作得很好。

问题是我想增加创建一个 ResourceBundle 的可能性,它在插件中并且只在插件中工作。

使用 URLClassLoaderReflections 加载插件。我无法访问(我不想)来自翻译 class 的插件 ClassLoaders。 因此,程序加载插件并稍后在插件内部执行一个方法(插件不在类路径中)并且该插件执行翻译方法。

为了实现这个,我想从调用方法中获取 ClassLoader 对象。

this or this 这样的东西可能有用,但我没有找到获取 Class/ClassLoader 而不是 class 的名称的方法。

我以为我可以使用 Stacktrace 来获取调用方法的 ClassLoader 但我只能使用 .getClassName 获取名称而没有 ClassClassLoader 的对象来电者。

这是我的:

翻译

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;
}

我不认为这种反复试验的方法是个好主意。也不是为每个字符串重新获取所有包。与仅让插件读取其包并对其调用 getString 相比,此翻译服务似乎甚至没有增加价值,至少不是证明代码的开销和复杂性合理的价值。

由于标准 ResourceBundle.getBundle 方法确实已经考虑了调用者的上下文,因此将字段声明和获取表达式放在插件中并调用 getString它并不比调用翻译服务的方法复杂。

为了完整起见,可以从 Java9 开始以标准方式获取调用者 class。然后,您可以像

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;
}