複数のクラスローダーでシングルトンを使用すると、問題に直面しています。たとえば、複数の EJB によってアクセスされるシングルトン。すべてのクラスローダーでインスタンスが 1 つしかないシングルトンを作成する方法はありますか?
カスタムクラスローダーまたはその他の方法を使用して、純粋な Java ソリューションを探しています。
唯一の方法は、シングルトン クラスを単一のクラスローダーによってロードすることです。たとえば、その jar ファイルを bootclasspath に配置します。
静的変数は、その変数を含むクラスをロードしたクラスローダーに本質的に関連付けられています。それはまさにそれが機能する方法です。絶対に 1 つのインスタンスが必要な場合は、そのクラスが 1 つのクラスローダーによってのみロードされる必要があります。
JavaEE アプリケーション サーバーは通常、シングルトンを「サービス」としてセットアップすることでこの問題を解決します。その正確な定義と構成は、問題のアプリケーション サーバーによって異なります。
たとえば、JBoss では、xyz-service.xml 記述子を使用して、JNDI または JMX ツリーからぶら下がるシングルトン オブジェクトを設定でき、アプリケーション コンポーネント (EJB など) はツリーからシングルトンを取得します。これにより、基礎となるクラスローダーのセマンティクスからある程度保護されます。
J2EE はクラスタリングを念頭に置いて設計されているため、J2EE がサポートする設計は、複数の JVM で動作する必要があります。あなたの質問から、クラスター化された環境について心配していないことがわかりました。そのため、アプリ サーバーの JNDI に簡単に挿入するだけで済みます。Glassfish では、これはライフサイクル リスナーと呼ばれます。起動後でも、シングルトンを JNDI に挿入し、それを見つけるために他のすべてに JNDI ルックアップを実行させます。
GlassFish は、クラスを JNDI にシリアル化して別のインスタンスを取得する可能性があるという点で、ここでも混乱する可能性があることに注意してください。1 つの JVM 内で実際にこれを行うとは思えませんが、実際に試してみるまでわかりません。
本当の最終的な答えは、J2EE はグローバルな真のシングルトンに対して敵対的であり、問題を回避する J2EE の方法はソリューションを再考することです。値を保持するデータベースや、データのインスタンスが 1 つだけ (データを表すオブジェクトの複数のインスタンスであっても) であることを保証できるその他の外部サービスのようなものは、J2EE の方法です。
TRUE を達成するSingleton
には、以下のガイドラインに従う必要があります。
final
ます。他の人はそれをサブクラス化して、もう 1 つのインスタンスを作成することはできませんprivate static final
private constructor
およびpublic getInstance()
方法。Singleton
このクラスがロードされていることを確認してくださいone ClassLoader only
readResolve()
逆シリアル化プロセスで新しいインスタンスを作成せずに、メソッドをオーバーライドして同じインスタンスを返します。サンプルコード:
final class LazySingleton {
private LazySingleton() {}
public static LazySingleton getInstance() {
return LazyHolder.INSTANCE;
}
private static class LazyHolder {
private static final LazySingleton INSTANCE = new LazySingleton();
}
private Object readResolve() {
return LazyHolder.INSTANCE;
}
}
詳細については、以下の SE の質問を参照してください。