2012-11-06 18 views
17

ServiceLoaderでロード可能なプラグインモジュールをビルドしたかったのです。これには、META-INF/servicesディレクトリにファイルを追加する必要があります。このファイルは、サービスインターフェイスの名前に基づいており、実装するクラスへの適格なパスが含まれています。その後、ServiceLoader.load()を呼び出してこれらのサービスを読み込むことができます。ここでJARとGradleのMETA-INF/services

は一例です:

たちはorg.example.plugins.PluginServiceと呼ばれるプラグインインターフェイスを提供したいと言います。次に、このサービスの実装をクラスorg.example.plugins.impl.ExamplePluginに提供します。

何らかのプラグインメカニズムが必要な場合は、実装が含まれているJARファイルを作成できます。このJARファイルには、ファイルMETA-INF/services/org.example.plugins.PluginServiceも含まれている必要があります。このファイルには、実装を見つけることがServiceLoaderを有効にするには、1つのライン

org.example.plugins.impl.ExamplePlugin 

が含まれている必要があります。そのJARファイルがビルド・パス内にある場合、あなたはServiceLoaderによって発見され、あまりにもすべてのプラグインにアクセスできるようになります

Iterator<PluginService> it = ServiceLoader.load(PluginService.class).iterator(); 

それイテレータを呼び出すことにより、プラグインを読み込むことができます。

Gradleには、デフォルトでMETA-INFディレクトリにファイルが含まれていないことがあります。結果のJARにそのようなファイルが含まれるようにする方法はありますか?

すでにmetaInfのメソッドが見つかりました。Jarです。しかし、自分で解決策を見つけ出すのに十分なことは分かりません。

+1

本当ですか?私のためにうまく動作します。どこにこのファイルを置くのですか? 'build.gradle'の見た目はどうですか? – axtavt

+0

メインソースフォルダ 'src/main/java'に' META-INF'ディレクトリがあります。ビルドスクリプトに特別なものは何もありません。それはほぼ標準的なもので、いくつかの追加の依存関係といくつかのカスタムリポジトリを含んでいます。 – pvorb

答えて

28

を期待通りに私の問題

jar { 
    from ('./src/main/java') { 
    include 'META-INF/services/org.example.plugins.PluginService' 
    } 
} 

今すぐJARファイルには、あなたがsrc/main/javaMETA-INF/services/org.example.plugins.PluginServiceを置くように見えますが、それは、それが元だていない解決リソースファイルであるため、Mavenディレクトリレイアウト規約に従ってresourcesフォルダに配置する必要があります。つまり、

src/main/resources/META-INF/services/org.example.plugins.PluginService 

この場合、すべての機能がそのまま使用できます。

5

一方私は(幾分)similar Questionで私の問題の解決策を見つけました。 gradle.buildファイルに以下を追加する

. 
|- org 
| `- example 
|  `- plugins 
|  `- impl 
|   `- ExamplePlugin.class 
`- META-INF 
    |- MANIFEST.MF 
    `- services 
     `- org.example.plugins.PluginService 
+0

唯一の回避策だと思うので、私は今は自分の答えを受け入れません。上で述べた@axtavtと同様に、 'build.gradle'ではこれらの行がなくても動作します。 – pvorb

0

mavenの規則に従わないいくつかのantベースのレガシーコードを継承した場合は、次のように役立ちます。

レガシー構造に合わせて、ソース・セットを定義し、このような行が含ま:ソース・セットで

include 'META-INF/services/**'

を。このパターンは一般的なもので、あなたのすべてのメタ情報サービスを拾うでしょう。

下記の完全な例。

sourceSets { 
    main { 
     java { 
      srcDir 'src' 
      exclude '**/Test*.java' 
     } 
     resources { 
      srcDir 'src' 
      include '**/*.xml' 
      include 'META-INF/services/**' 
     } 
    } 
    test { 
     java { 
      srcDir 'src' 
      include '**/Test*.java' 

     } 
     resources { srcDir 'resources' } 
    } 
} 
関連する問題