为什么我的ResourceBundleControlProvider没有加载?

时间:2014-06-13 00:02:10

标签: java internationalization resourcebundle

我以为我会在Java 8中使用新的ResourceBundleControlProvider框架来修复Oracle本身永远无法修复的东西 - 读取资源包时使用的默认编码。

所以我做了一个控件:

package com.acme.resources;

import java.io.IOException;
import java.util.Locale;
import java.util.ResourceBundle;

public class AcmeResourceBundleControl extends ResourceBundle.Control
{
    @Override
    public ResourceBundle newBundle(String baseName, Locale locale, String format,
                                    ClassLoader loader, boolean reload)
        throws IllegalAccessException, InstantiationException, IOException
    {
        throw new UnsupportedOperationException("TODO");
    }
}

然后我做了一个提供者:

package com.acme.resources;

import java.util.ResourceBundle;
import java.util.spi.ResourceBundleControlProvider;

public class AcmeResourceBundleControlProvider implements ResourceBundleControlProvider
{
    private static final ResourceBundle.Control CONTROL = new AcmeResourceBundleControl();

    @Override
    public ResourceBundle.Control getControl(String baseName)
    {
        if (baseName.startsWith("com.acme."))
        {
            return CONTROL;
        }
        else
        {
            return null;
        }
    }
}

然后在META-INF / services / java.util.spi.ResourceBundleControlProvider中:

com.acme.resources.AcmeResourceBundleControlProvider

然后我只是尝试从IDEA运行我们的应用程序,我发现它从不加载我的提供程序(否则会引发异常。)

我检查了名字,他们似乎都匹配了。我检查了IDEA正在使用的编译器输出目录,它确实包含服务文件。我写了一个简单的测试程序,它只是试图查找服务:

public static void main(String[] args)
{
    for (ResourceBundleControlProvider provider :
         ServiceLoader.load(ResourceBundleControlProvider.class))
    {
        System.out.println(provider.getClass());
    }
}

这会打印出一个条目,这是我的实现类的名称。所以问题是服务文件中的不是

如果我在ResourceBundle中断点,我似乎能够访问自定义提供程序类。最初尝试调试器显示ServiceLoader没有找到任何实现,但我无法弄清楚原因。我确定有一些狡猾的类加载器魔法正在进行,这导致我的课程没有加载。 :(

the Javadoc上的一些可怕文档使得它可能必须作为全局扩展安装。如果确实如此,那有点遗憾,因为它似乎是一种有用的方式来覆盖默认(以及我认为已经破坏)的行为。但是我也在这个问题上阅读了the tutorial,它似乎没有描述这样的事情(除非在最后一分钟从Java 8中取出好的行为并且文档已经过时了!)< / p>

2 个答案:

答案 0 :(得分:4)

本教程确实声明包含ResourceBundleControlProvider的JAR必须位于JVM的系统扩展目录中。 tutorial的第6节描述了要求:

  

java -Djava.ext.dirs = lib -cp build RBCPTest

     

安装Java扩展时,通常将扩展的JAR文件放在JRE的lib / ext目录中。但是,此命令指定包含具有系统属性java.ext.dirs。

的Java扩展的目录

ServiceLoader.loadInstalled()的JavaDoc还声明应用程序类路径上的提供程序被忽略。

答案 1 :(得分:0)

您的问题是JVM附带的java.util.ResourceBundle执行ServiceLoader.loadInstalled(ResourceBundleControlProvider.class)以获取静态初始化程序中的提供程序列表,并使用此后获得的列表。