2

プラグインをメインアプリケーションから分離するのに役立つカスタムクラスローダーをScalaに実装しました。現在、メインアプリケーションがプラグインコードを使用できるように、共有ルートオブジェクトとして機能するJavaインターフェイスが必要です。

共有ルートとして機能するインターフェース(これをScalaにしたい):

public interface Handler {
    public List<HandlerInfo> getHandlers();
}

プラグインの例:

class MyPlugin extends Handler {
  def getHandlers: java.util.List[HandlerInfo] = // get some handlers
}

アプリケーションでの使用法:

val jarFile     = new File(System.getProperty("user.dir") + "/plugins/" + jarName)
val cl          = new PluginLoader(jarFile, this.getClass.getClassLoader) // my custom classloader
val classToLoad = Class.forName(className, true, cl)
val handler     = classToLoad.newInstance.asInstanceOf[Handler]
val handlers    = handler.getHandlers

これは正常に機能しますが、私の問題は、この1つのJavaクラス(および結果のビルド構成)を保持する必要があることです。代わりに、次のようなScalaトレイトまたは抽象クラスを使用したいと思います。

trait Handler {
  def getHandlers : List[HandlerInfo]
}

次に、私のプラグインは次のようになります。

class MyPlugin extends Handler {
  def getHandlers: List[HandlerInfo] = // no more java.util.List
}

しかし、私はこれを行うことはできません、なぜならこの行は

val handler     = classToLoad.newInstance.asInstanceOf[Handler]

ClassCastExceptionおそらく、ScalaコンパイラがきれいなJavaインターフェイスを生成しないためにをスローします。これを回避する方法はありますか?Scalaのみのプロジェクトを作成できますか?

4

1 に答える 1

1

問題は、あなたが思っている場所ではありません。クラスローダーのどこかにあります。デフォルトのクラスローダーは、Javaのものでも問題なく動作します。証拠:

// File Handler.scala
trait Handler { def getHandlers: List[String] }

// File MyPlugin.scala
class MyPlugin extends Handler { def getHandlers = List("salmon", "cod") }

// File Interop.java
public class Interop {
  public static void main(String[] args) {
    try {
      Class classToLoad = Class.forName("MyPlugin");
      Handler handler = (Handler)classToLoad.newInstance();
      System.out.println("Class loader = "+handler.getClass().getClassLoader());
      System.out.println(handler.getHandlers());
    }
    catch (Exception e) { System.out.println("Uh-oh: "+e); }
  }
}

そしてここでそれを実行します:

$ java -cp .:/usr/share/scala/2.10/lib/scala-library.jar Interop
Class loader = sun.misc.Launcher$AppClassLoader@1f3e8d89
List(salmon, cod)
$

ScalaListとすべてのもの、そしてデフォルトのJavaクラスローダーによってロードされた新しいクラスを使用します。

于 2013-01-22T20:58:13.433 に答える