4

私のライブラリのコードでは、後で.を使用してインスタンス化するために、JAXBを使用してXMLファイルからクラス名をロードしますClass.forName()。ケースを説明するための架空の例:

public void libraryMethod() throws Exception {
  List<String> classNames = loadClassNamesFromXML();

  for (String className : classNames) {
    Class.forName(className).newInstance().doThings();
  }
}

現在、一部のユーザーはOSGiを使用してアプリケーションを構成し、XML構造を使用して構成するクラスとは異なるクラスローダーを使用してライブラリをロードします。これは、クラスが見つからないため、ロードが失敗する可能性があることを意味します。

そのようなクラスをロードするためのより信頼できる方法はありますか?または、これらのインスタンスを構成する他の方法はありますか?私はこれをもたらす提案を受け入れています:

public void libraryMethod() throws Exception {
  // Spring does things like this:
  List<SomeType> instances = loadInstancesFromXML();

  for (SomeType instance : instances) {
    instance.doThings();
  }
}

いくつかの制約:

  • ライブラリの観点からは、これらのインスタンスのライフサイクルは重要ではありません。彼らが(ユーザー)状態を持っている場合、私のライブラリは気付かないでしょう。
  • このライブラリでは物事をシンプルに保ちたいので、たとえばSpringなどの構成フレームワークに外部依存関係を作成することは避けたいと思います。したがって、私は標準のJDK6+ディストリビューションで実現できるソリューションにのみ興味があります。
  • 単純なXML構成ファイルを保持したいと思います(XML構造に少し変更しても問題ありません)。
4

4 に答える 4

3

ライブラリを柔軟にし、OSGi環境と非OSGi環境の両方で機能させる場合は、ユーザーが独自のClassLoaderを提供できるようにするか、ライブラリにどのクラス名を使用しているかをユーザーに通知させる必要があります。NeilBartlettのブログ投稿を読んでください。

元のリンクは404を返します。WaybackMachineの記事にアクセスできます。

于 2012-07-14T16:30:34.783 に答える
2

一般に、OSGiではサービスを使用する必要があります。Class.forName / XML構成が非常に人気がある理由は、単一のクラスのみが制御を取得するためです。残りを構成するには、初期化/呼び出すクラスを知っている必要があります。

OSGiでは、各モジュール(バンドル)が宣言型サービスを介して(または昔ながらの方法でアクティベーターを介して)制御を取得できるため、この問題は存在しません。したがって、OSGiにはピアツーピアモデルがあります。誰でもサービスを登録でき、他のサービスに依存できます。

したがって、クラス名を指定してグローバルに一意であると想定する(大規模なシステムではない)代わりに、サービスを使用してJavaコンパイラーを離れない方がはるかに簡単です。これらのクラス名は非常にエラーが発生しやすいです。一般に、これは、クライアントを初期化する必要がないため、サービスを登録して呼び出されるのを待つことが多いことを意味します。ただし、ホワイトボードパターンは、クライアントについて知りたい場合の状況に対応しています(bndtoolsとbndアノテーションを使用)。

サーバー"

@Component
public class MyLib {
   @Reference(type='*')
   void addSomeType(SomeType st ) {
      st.doThings();
   }
}

クライアント

@Component
public class MyClient implements SomeType {
  public void doThings() { ... }
}

お役に立てれば。

于 2012-07-16T13:58:54.980 に答える
2

説明してくれてありがとう。春はOSGiでこれを簡単にすることはありません。インポートしないパッケージから実装クラスを単純に注入することはできません。OSGiでは、通常、OSGiサービスを使用して、バンドルの外部で発生し、コンパイル時に不明な実装を注入します。

したがって、ユーザーは指定したインターフェースを実装し、その実装をOSGiサービスとして公開します。次に、そのようなサービスをすべて取得するか、ユーザーがxml構成でサービスのLDAPフィルターを指定できるようにします。

このアプローチの利点は、クラスをロードしたり、クラスローダーを気にしたりする必要がないことです。したがって、これはOSGiで推奨される方法です。OSGi Ivanのアプローチの内側と外側で同じソリューションが必要な場合は、クラスローダー+クラス名を指定することもできます。

于 2012-07-14T21:06:36.287 に答える
1

JDBC4ドライバーには、jar内のMETA-INF / services / java.sql.Driverが含まれ、ServiceProviderメカニズムを使用してドライバー実装をJVMに登録します(java.util.ServiceLoader javadocsを参照)。クラスパスにドライバーを配置すると、ドライバーが自動的に登録されるため、Class.forNameを使用する必要がなくなります。代わりに、アプリコードはServiceLoader.loadを使用して登録済みドライバーを検出します。同じメカニズムを他の構成に使用できます。おそらくそのようなものを使用することができますか?余談ですが、独自の実装をサービスプロバイダーメカニズムに登録する場合、spiのようなアノテーションを使用すると非常に便利に見えます。

于 2012-07-14T19:29:13.187 に答える