0

我必须依赖第三方库,它期望某些东西在类路径中。好像用

ResourceBundle.getBundle("cmbcmenv");

获取属性文件。此文件的位置由安装连接器时设置的环境变量指定(它创建一个变量“IBMCMROOT”,指向包含该文件的目录)。我不能在我的类路径中使用相对路径或绝对路径,因为连接器的安装目录可能会有所不同。

我试过像这样手动添加一个新的 ClassLoader:

ClassLoader defaultLoader = Thread.currentThread().getContextClassLoader();     
        String config = System.getenv().get("IBMCMROOT")+"/cmgmt";      
        URLClassLoader loader = URLClassLoader.newInstance(new URL[]{new File(config).toURI().toURL()},defaultLoader);
        Thread.currentThread().setContextClassLoader(loader);           

这在 getBundle 上也失败了。由于它是第三方库,我无法使用

ResourceBundle.getBundle("cmbcmenv",Locale.getDefault(),loader);

不然不会有这个问题。。

如何强制 ResourceBundle 使用特定的 ClassLoader?似乎 getBundle 使用 CallerClassloader 或 SystemClassloader 但没有办法影响它,对吧?

4

1 回答 1

1

您可以使用与在键中实际查找不同的值来欺骗ResourceBundle类以缓存捆绑实例。ClassLoader

ResourceBundle rb=ResourceBundle.getBundle("Resources", new ResourceBundle.Control() {
  @Override
  public long getTimeToLive(String baseName, Locale locale) {
    return Long.MAX_VALUE;
  }
  @Override
  public ResourceBundle newBundle(String baseName, Locale locale,
      String format, ClassLoader loader, boolean reload)
      throws IllegalAccessException, InstantiationException, IOException {
    return super.newBundle(baseName, locale, format, defaultLoader, reload);
  }
});

请注意,getBundle调用使用默认的 SystemClassLoader (或 caller ClassLoader),因为没有指定类加载器。这是ClassLoader用于缓存结果的键。但是在查找真正的包时,自定义Control实现会替换为ClassLoader您的实例。defaultLoader

请注意,您应该在 3rd 方库的查找操作之前执行此操作。此控件表示捆绑包永远不会过期,但当 JVM 内存不足时,它仍可能会被释放。

请注意,它还会缓存失败,因此必须在其他人尝试查找该捆绑包之前应用ResourceBundle此技巧。

于 2013-10-23T16:54:43.120 回答