5

効果的なJavaの第2章で説明されているように、「サービスプロバイダーフレームワーク」を参照しStringます。これは、実行時にいくつかのクラスの1つをインスタンス化する必要がある、問題を処理するための正確な方法のようです。サービス、およびConfigurationオブジェクト(基本的にはXMLスニペット):

しかし、どうすれば個々のサービスプロバイダー(たとえば、多数のデフォルトプロバイダーといくつかのカスタムプロバイダー)に自分自身を登録させることができますか?

 interface FooAlgorithm
 {
     /* methods particular to this class of algorithms */
 }

 interface FooAlgorithmProvider
 {
     public FooAlgorithm getAlgorithm(Configuration c);
 }

 class FooAlgorithmRegistry
 {
     private FooAlgorithmRegistry() {}
     static private final Map<String, FooAlgorithmProvider> directory =
        new HashMap<String, FooAlgorithmProvider>();
     static public FooAlgorithmProvider getProvider(String name)
     {
         return directory.get(serviceName);
     }
     static public boolean registerProvider(String name, 
         FooAlgorithmProvider provider)
     {
         if (directory.containsKey(name))
            return false;
         directory.put(name, provider);
         return true;
     }
 }

たとえば、カスタムクラスMyFooAlgorithmとMyFooAlgorithmProviderを記述してFooAlgorithmを実装し、それらをjarに配布する場合、registerProviderを自動的に呼び出す方法はありますか、またはアルゴリズムを使用するクライアントプログラムはFooAlgorithmRegistry.registerProvider( )使用したいクラスごとに?

4

2 に答える 2

10

META-INF/services/fully.qualified.ClassName を作成してそこにリストする必要があると思いますが、仕様 ( JAR ファイル仕様またはthis ) を覚えていません。

Java アーキテクトの本の第 8 章の実用的な API 設計の告白は、 SPI に関するものです。

ServiceLoader は、利用可能な実装を一覧表示するのに役立つ場合があります。たとえば、PersistenceProvider インターフェースでは次のようになります。

ServiceLoader<PersistenceProvider> loader = 
        ServiceLoader.load(PersistenceProvider.class);
Iterator<PersistenceProvider> implementations = loader.iterator();
while(implementations.hasNext()) {
    PersistenceProvider implementation = implementations.next();
    logger.info("PersistenceProvider implementation: " + implementation);
}
于 2009-07-17T18:34:09.650 に答える
1

次のように、クライアント JAR で、前に呼び出されることがわかっているクラス内の静的イニシャライザ ブロックにプロバイダを登録することができますFooAlgorithmRegistry.getProvider()

static {
    FooAlgorithmRegistry.registerProvider("test", new MyFooAlgorithmProvider());
}

しかし、ファクトリのアクセサ メソッドの前でこれが実行されることを保証する方法を見つけるのはかなり難しいかもしれません (静的イニシャライザは、クラスが最初にロードされるときに 1 回だけ実行されることが保証されます)。

于 2009-07-17T18:44:38.363 に答える