私はJavaが初めてです(C#.NETのバックグラウンドから来ました)。Google Guice と ServiceLoader を組み合わせて「拡張/IoC」スタイルのアーキテクチャを作成しようとしていますが、Java 1.7.0_75 と IntelliJ IDEA 14 を実行している ServiceLoader 部分を動作させることができないようです。
プロジェクト内にモジュールがあります。これは事実上、com.vipro.bcl.SimplePluginLoader というインターフェイスを含む ViProJ.Bcl という基本クラス ライブラリです。
com.vipro.test.TestModule1 という SimpleModuleLoader の単一の実装を含む ViProJ.TestModules という別のモジュールがあります。
私の src フォルダー内には、com.vipro.bcl.SimpleModuleLoader という単一のファイルを含む META-INF.services というフォルダーを含むリソース フォルダー (モジュール設定画面内のリソースとしてマークされている) があります。このファイル内の値は com.vipro.test.TestModule1 です。
IntelliJ によって (同じディレクトリに) 2 つのアーティファクトが作成されています。1 つ目は、コマンド ラインから実行される Main 関数を含むモジュールです。次のようにサービスローダーをロードします。
ServiceLoader<SimpleModuleLoader> loader = ServiceLoader.load(SimpleModuleLoader.class);
もう 1 つは、前述のテスト ライブラリです。これをデバッグすると、サービス ローダーにクラスが含まれていないため、クラスのエクスポートが機能していません。
7zip の jar ファイルを開くと、META-INF\services\com.vipro.bcl.SimpleModuleLoader が表示されるため、IntelliJ はこれらのファイルを正しくパッケージ化しています。
MANIFEST.MF ファイルは次のようになります。
Manifest-Version: 1.0
Export-Package: com.google.inject.name;version="1.3",com.google.inject
.binder;version="1.3",com.google.inject.spi;version="1.3",com.google.
inject.matcher;version="1.3",com.google.inject.util;version="1.3",com
.google.inject;version="1.3"
Bundle-Name: guice
Created-By: 1.6.0_23 (Sun Microsystems Inc.)
Bundle-RequiredExecutionEnvironment: J2SE-1.5,JavaSE-1.6
Bundle-Copyright: Copyright (C) 2006 Google Inc.
Ant-Version: Apache Ant 1.7.1
Bundle-Vendor: Google, Inc.
Bundle-Version: 3.0
Bundle-ManifestVersion: 2
Bundle-Description: Guice is a lightweight dependency injection framew
ork for Java 5 and above
Bundle-License: http://www.apache.org/licenses/LICENSE-2.0.txt
Bundle-SymbolicName: com.google.inject
Import-Package: javax.inject,org.aopalliance.intercept
Bundle-DocURL: http://code.google.com/p/google-guice/
マニフェストが私のモジュールではなく Guice について話している理由がよくわかりませんか? おそらくこれが失敗する原因ではありませんか?これが機能しない理由を誰か教えてもらえますか? 必要なものをすべて提供していないことは確かですが、ここに他に何を含める必要があるか本当にわかりませんか?
モジュールModule
は、ビルドに pom.xml (Maven) の代わりに .impl ファイルを使用しています。これは次のようになります。
<?xml version="1.0" encoding="UTF-8"?>
<module type="JAVA_MODULE" version="4">
<component name="NewModuleRootManager" inherit-compiler-output="true">
<exclude-output />
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/src/resources" type="java-resource" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module" module-name="ViProJ.Bcl" />
<orderEntry type="library" name="guice-3.0" level="project" />
<orderEntry type="library" name="guice-multibindings-3.0" level="project" />
</component>
</module>
私の注入コードは、次のように MultiBinder を使用します。
// dynamic modules via service loader
Multibinder<IModule> modBinder = Multibinder.newSetBinder(binder(), IModule.class);
ServiceLoader<SimpleModuleLoader> loader = ServiceLoader.load(SimpleModuleLoader.class);
for (SimpleModuleLoader moduleLoader : loader) {
for (Class<? extends IModule> moduleClass : moduleLoader.getModules()) {
System.out.print("Found expansion module");
modBinder.addBinding().to(moduleClass);
}
}