2014-06-13 3 views
3

Java 8에서 새 ResourceBundleControlProvider 프레임 워크를 사용하여 Oracle 자체에서 수정하지 않을 항목 (자원 번들을 읽을 때 사용되는 기본 인코딩)을 수정한다고 생각했습니다.내 ResourceBundleControlProvider가로드되지 않는 이유는 무엇입니까?

에서 다음
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/서비스/java.util.spi.ResourceBundleControlProvider :

com.acme.resources.AcmeResourceBundleControlProvider 

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

가 그럼 난 공급자를 만든 :

그래서 내가 컨트롤을 만든

그런 다음 방금 IDEA에서 애플리케이션을 실행하려고 시도했지만 내 제공자가로드되지 않는다는 것을 알았습니다 (그렇지 않으면 excepti 에 제기 될 것입니다.)

나는 이름을 확인하고 모두 일치하는 것 같습니다. IDEA가 사용하는 컴파일러 출력 디렉토리를 점검했고 서비스 파일을 포함합니다. 난 그냥 서비스를 검색하려고 간단한 테스트 프로그램을 작성 :

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

이 인쇄 밖으로 내 구현 클래스의 이름을 하나 개의 항목을 수행합니다. 따라서 문제는 서비스 파일에 이 아니고이 아닙니다.

ResourceBundle 내에서 중단 점이 있으면 사용자 지정 공급자 클래스에 액세스 할 수있는 것 같습니다. 디버거에 처음 들어가면 ServiceLoader가 구현을 찾지 못했지만 그 이유는 알 수 없습니다. 내 클래스를로드하지 않는 결과를 가져 오는 dodgy 클래스 로더 마법이 있다고 확신합니다. :(

the Javadoc에 대한 몇 가지 무서운 문서는 글로벌 확장 프로그램으로 설치해야하는 것처럼 들리지만, 실제로 그렇다면 매우 유용합니다. 기본 (그리고 내 의견으로는 깨진) 행동.하지만 그 문제에 대해서도 the tutorial을 읽었습니다. 그런 식으로는 설명하지 못했습니다 (좋은 행동이 자바 8에서 막판에 나오지 않는 한, 문서는 out of date!)

+0

수동으로 애플리케이션을 jar 한 다음 jar (디렉토리 구조 보장)를 실행하면 어떻게됩니까? 나는 IDEA 사용자는 아니지만, 단지'META-INF/services/java.util.spi.ResourceBundleControlProvider'가 런타임 클래스 경로에 없거나 검사되지 않습니다. – Muel

+0

항아리에서 실행하면 내 공급자에게 전화하는 것 같지 않습니다. 이상하게도, * my * 코드의 ServiceLoader.load()는 공급자를 찾았지만, ResourceBundle.getBundle()은 그렇지 않습니다. 이것은 공급자 프레임 워크를 가지고있는 목적을 무력화시키는 것 같습니다. :/ – Trejkaz

답변

4

이 자습서에서는 ResourceBundleControlProvider이 포함 된 JAR이 JVM의 시스템 확장 디렉토리에 있어야한다고 설명합니다.

자바는 자바 확장을 설치하면 일반적으로의 확장의 JAR 파일을 넣어

RBCPTest를 구축 -cp -Djava.ext.dirs = lib에 다음 tutorial 제 6 요구 사항을 설명합니다 JRE의 lib/ext 디렉토리 그러나이 명령은 java.ext.dirs 시스템 특성을 갖는 Java 확장을 포함하는 디렉토리를 지정합니다.

ServiceLoader.loadInstalled()의 JavaDoc에는 응용 프로그램의 클래스 경로에있는 공급자가 무시된다는 내용도 나와 있습니다.

+1

그래, 그렇게 보인다. 그래서 우리가 열심히 기다리고 있던 또 다른 기능은 아무도 사용할 수없는 지점까지 불구가되었습니다. 얼마나 좋은지. – Trejkaz

0

문제는 JVM과 함께 제공되는 java.util.ResourceBundle이 ServiceLoader.loadInstalled (ResourceBundleControlProvider.class)를 사용하여 정적 초기화 프로그램에서 공급자 목록을 얻고 이렇게 얻은 것을 사용한다는 것입니다. 이후의 목록.

관련 문제