私は、人々がプラグイン フレームワークを使用して特定のインターフェイスの実装を提供できるようにするライブラリを作成しています (よく知られている場合は JPF です)。プラグインはクラスパスに保存されません。フレームワークはプラグインごとに ClassLoader を提供するので、インターフェース「MyInterface」の「MyImpl」という名前の実装が要求されると、正しいプラグインを見つけて、そのプラグインの ClassLoader を使用してクラスをロードし、そこからインスタンスを作成できます。コンストラクターについて何か知っていれば。ここまでは順調ですね。
ただし、特定の実装でのみ使用できるメソッドを呼び出す必要がある場合があります。したがって、これを行うには2つの方法があります。
方法 1:
// Makes sure that MyImpl has been loaded, using the custom classloader
Plugins.getClass(MyInterface.class, "MyImpl");
// This line will not compile because MyImpl is not available at build time
MyImpl foo = new MyImpl();
// If I could get this far, this line would work:
foo.methodOnlyInMyImpl();
方法 2:
// This call will get an instance of MyImpl (already written and tested)
MyInterface foo = Plugins.getInstance(MyInterface.class, "MyImpl");
// Compiler error because there is no MyInterface.methodOnlyInMyImpl method.
foo.methodOnlyInMyImpl()
方法 1 は、クラスが「通常」であり、プラグイン経由でアクセスできない場合にコードを記述する方法に最も似ているため、2 つのうちのよりクリーンな方法です。ただし、どちらもコンパイルされません。
これまでに思いついたオプション:
A. 方法 2 を使用しますが、リフレクションを使用して methodOnlyInMyImpl メソッド呼び出しを行います (どうか、いいえ!)
B. ビルド パスにプラグイン クラスを配置してから、コンパイルされる方法 1 を使用します。 . (私の現在のお気に入り)
C. B + プラグインがインストールされたら、クラスファイルをクラスパスにある別のディレクトリにコピーして、システムのクラスローダーがそれらをロードできるようにします (他の問題を引き起こします)
だから、私の質問は次のとおりです。
- より良い別のアイデアがありませんか?
- B を実行すると、実行時に問題が発生しますか? 結局、MyImpl を使用するクラスは、おそらくシステム クラスローダーを使用してロードされます。では、 が表示されるとすぐに
MyImpl foo
、システム クラスローダを使用して MyImpl をロードしようとしませんか? これは失敗します (Plugins.newInstance 呼び出しが MyImpl のインスタンスを提供する場合でも)。