タスクと初期調査
1 つの Java Swing アプリケーションで 2 つの Oracle Coherence ニア キャッシュ インスタンスを設定しようとしています。解決策のアイデアはここにあります。私のケースはもう少し複雑で、ここからゲームが始まります。
簡単な説明
私の場合、アカウント サービスがあります。SIT と UAT の 2 つのエンドポイントを持つことができます。このようなサービスを 2 つ作成するには、システム変数 ( tangosol.coherence.cacheconfig ) でエンドポイントをオーバーライドするために、Coherence の 2 つの「インスタンス」をロードする必要があります。
私は持っている:
- アプリのメイン コードは mainapp.jar にあります。
- account-interfaces.jar にあるAccountServiceインターフェース。
- account-impl.jar にあり、AccountServiceインターフェースを実装するAccountServiceImplクラス。
- 私の主なアプリケーションは次の構造を持っています
bin: startup.bat, startup.sh conf: app.properties lib: mainapp.jar, account-interfaces.jar, account-impl.jar, coherence.jar
試みたアプローチ
私は専用の子優先クラスローダー - InverseClassLoader を作成し、AppLaunchClassLoader (デフォルトの Thread.currentThread().GetContextClassLoader() クラスローダー) を親にしました。InverseClassLoader を使用して、AccountServiceImpl クラスをロードします。
Class<AccountServiceImpl> acImplClass = contextClassLoader.selfLoad(AccountServiceImpl.class).loadClass(AccountServiceImpl.class);
Constructor<AccountServiceImpl> acConstructor =
acImplClass .getConstructor(String.class);
AccountService acService = acConstructor .newInstance(serviceURL);
問題と質問
- 「AccountServiceImpl を AccountService にキャストできません」という例外が発生します。これは、これら 2 つのクラスが異なるクラスローダーによってロードされたことを意味します。しかし、それらのクラスローダは親子関係にあります。クラスが親 (インターフェース - 'abstract' タイプ) によってロードされたとしても、子クラスローダーによってロードされたクラス (concrete impl) では使用できないというのは正しいですか? では、なぜこの親子関係が必要なのでしょうか。
- コードで AccountService インターフェイスを指定したところ、デフォルトのクラスローダーによって読み込まれました。上記のコードをスレッドにラップして、コンテキストクラスローダーである InverseClassLoader を設定しようとしました。何も変わっていません。そのようなインターフェイス実装コーディング (通常のコーディング) を使用できず、常にリフレクションを使用して具体的なメソッドを常に呼び出す必要があるというのは正しいですか? (解決策があることを願っています);
- たとえば、InverseClassLoader によって読み込まれる AccountService クラスと AccountServiceImpl クラスの両方をリストしました。これら 2 つのクラスからアクセスできる他のクラスを、InverseClassLoader によってもロードする必要がある場合はどうすればよいでしょうか? すべての「関連する」クラスを同じクラスローダーでロードする必要があると言う方法はありますか?
アップデート
InverseClassLoader は次のとおりです。
public class InvertedClassLoader extends URLClassLoader {
private final Set<String> classesToNotDelegate = new HashSet<>();
public InvertedClassLoader(URL... urls) {
super(urls, Thread.currentThread().getContextClassLoader());
}
public InvertedClassLoader selfLoad(Class<?> classToNotDelegate) {
classesToNotDelegate.add(classToNotDelegate.getName());
return this;
}
@Override
public Class<?> loadClass(String className, boolean resolve) throws ClassNotFoundException {
if (shouldNotDelegate(className)) {
System.out.println("CHILD LOADER: " + className);
Class<?> clazz = findClass(className);
if (resolve) {
resolveClass(clazz);
}
return clazz;
}
else {
System.out.println("PARENT LOADER: " + className);
return super.loadClass(className, resolve);
}
}
public <T> Class<T> loadClass(Class<? extends T> classToLoad) throws ClassNotFoundException {
final Class<?> clazz = loadClass(classToLoad.getName());
@SuppressWarnings("unchecked")
final Class<T> castedClass = (Class<T>) clazz;
return castedClass;
}
private boolean shouldNotDelegate(String className) {
if (classesToNotDelegate.contains(className) || className.contains("tangosol") ) {
return true;
}
return false;
}