2016-08-26 9 views
1

私はいくつかのMavenモジュールで構成されるライブラリ用の拡張モジュールを書いています。私は1つのモジュールの上にいくつかの機能を追加する必要がありますが、誰かが私の拡張子(典型的な使用例)なしでこのモジュールを使いたい場合に備えて、不要な依存性を追加したくありません。別のモジュールにランタイム依存関係を追加するにはどうすればいいですか?

私が考えることができる1つの解決策は、拡張モジュールで別のモジュールを作成し、リフレクションを使用してそのクラスからメソッドを呼び出そうとすることです。

try { 
    Class.forName("my.package.Foo", false, getClass().getClassLoader()); 
    // extension will be enabled and some method will be called using reflection 
} catch(ClassNotFoundException e) { 
    // extension will be disabled 
} 

このクラスのメソッドは、クラスパス上にある場合にのみ呼び出されます。拡張モジュールは、モジュールにMaven依存関係を追加した場合(拡張モジュールへの依存性に加えて)、Maven依存関係を追加すると有効になります。

しかし、これは最善のアプローチのようには聞こえません。この問題に対して、より洗練されたソリューションがありますか?

答えて

1

1つの方法は、組み込みのService provider interface (SPI)を使用することです。

基本的な考え方は、いくつかのインタフェース(サービス)の実装を提供するためのオプションのライブラリを作成することです。これはメインアプリケーションで簡単に見つかるかもしれません。この例を見てください

// scan classpath for all registered 
// implementations of Module interface 
ServiceLoader<Module> loader = ServiceLoader.load(Module.class); 
for (Module module : loader) { 
    module.doSomething(); 
} 

オプションの依存関係がクラスパスサービスローダーに見つかると、それが見つかります。

多くの例は、オラクルの"Creating Extensible Applications"チュートリアルで見つけることができます。

もう1つの方法は、springまたはgoogle guiceのような依存性注入フレームワークを使用することです。これらのフレームワークは、クラスパスを自動的にコンポーネントディスカバリのためにスキャンするメカニズムも提供しています。この解決方法は、より柔軟であるが、SPIより重い方法です。

0

あなたが言及したように新しいモジュールを作成することが最も簡単です。この新しいプロジェクトAでは、プロジェクトBについて話しているこの既存のモジュールに依存しています。 これで、あなたの内線を使わずに使いたい人は、プロジェクトBを使用します。あなたの内線が必要な人は、プロジェクトA ClassNotFoundの競合を避けるために、Maven依存関係をビルドパスに追加してください。

1

することができます明確なこのようなあなたの依存関係:

<dependency> 
    <groupId>com.thoughtworks.paranamer</groupId> 
    <artifactId>paranamer</artifactId> 
    <version>2.6</version> 
    <optional>true</optional> 
</dependency> 

チェックアウトこのlink

から詳細
関連する問題