2009-09-29 3 views
5

複数のクラスローダー間で使用されている場合、私のシングルトンに問題があります。たとえば、複数のEJBによってアクセスされるシングルトン。すべてのクラスローダーでインスタンスが1つしかないシングルトンを作成する方法はありますか?Javaで真のシングルトンを作成するには?

私は純粋なJavaソリューションのカスタムクラスローダーまたは他の方法を使用して探しています。

+0

多分それは役立ちますhttp://stackoverflow.com/questions/70689/efficient -way-to-implement-singleton-in-java – Chris

+0

どのようなアプリケーションサーバーを使用していますか? –

+4

自分のブログをPRしていますか?それはあなたのプロフィールが言うことです。だから "私はリンクを発見"は本当に "私はその投稿を書いた"です。 – ChssPly76

答えて

5

唯一の方法は、シングルトンクラスを単一のクラスローダーでロードすることです。たとえば、jarファイルをbootclasspathに入れます。

静的変数は、その変数を含むクラスをロードしたクラスローダーに本質的に結び付けられています。それはちょうどそれが動作する方法です。 1つのインスタンスが絶対に必要な場合は、そのクラスを1つのクラスローダーでのみロードする必要があります。

+0

私たちはGlassfish AppサーバーとOpenESBをEnterrpriseサービスバスとして使用します。このシングルトン(Ldap Search結果を格納するためのJCS Cacheへのラッパー)は、複数のバインディング・コンポーネントとEJBの間で共有される共通ライブラリーの一部です。 – rjoshi

+0

@rjoshi:シングルトンは複数のクラスローダーにロードされていますか?これを回避できますか?クラスが常に複数のクラスローダーになる場合は、それが「適切な」シングルトンではないことを避けることができません。 –

+0

また、シリアライズ/デシリアライズに注意してください。ベストプラクティスはおそらくシングルトンをシリアライズ可能にすることを避けることです。 – CPerkins

5

JavaEEアプリケーションサーバーは、シングルトンを「サービス」として設定することでこの問題を解決します。その正確な定義と構成は、問題のアプリケーションサーバーによって異なります。

たとえば、JBossでは、xyz-service.xml記述子を使用してJNDIまたはJMXツリーからハングするシングルトンオブジェクトを設定し、アプリケーションコンポーネント(EJBなど)がツリーからシングルトンをフェッチすることができます。これは、基本的なクラスローダーのセマンティクスからあなたをある程度保護します。

+0

Glassfish AppサーバーとOpenESBをエンタープライズサービスバスとして使用しています。このシングルトンは、複数のバインディングコンポーネントとEJB間で共有される共通ライブラリの一部です。 – rjoshi

+2

OK、GlassfishでJMXサービスを作成し、コンポーネントからそのサービスに接続する方法を確認してください。 – skaffman

+0

私はグーグルフィッシュV3のシングルトン機能を備えたEJB3.1のサポート以外は何も見つかりませんでした。 Glassfish 2.1GAでEJB3を使用しています。 – rjoshi

3

J2EEはクラスタリングを考慮して設計されているため、サポートする設計は複数のJVMで動作する必要があります。あなたの質問から、あなたがクラスタ化された環境を気にしていないので、アプリケーションサーバー上のJNDIに簡単に挿入する必要があります。グラスフィッシュでは、それはlifecycle listenerと呼ばれます。起動した後でも、シングルトンをJNDIに挿入してから、他のすべてがJNDIルックアップを検索して見つけます。

ここでも、GlassFishはクラスをJNDIにシリアル化して、異なるインスタンスを取得できるという点で、ここであなたを混乱させる可能性があることに注意してください。私はそれが実際には1つのJVM内でこれを行うのではないかと疑いますが、試してみるまで知りません。

本当の根本的な答えは、J2EEがグローバルな真のシングルトンに敵対していることです。問題を取り巻くJ2EEのやり方は、ソリューションを再考することです。データを表すオブジェクトの複数のインスタンスが存在する場合でも、データのインスタンスが1つしか存在しないことを保証できる値やその他の外部サービスを保持するデータベースのようなものが、J2EEの方法です。

+0

私はこのシングルトンを使ってldapキャッシュを保存しています。私は他の開発者がこの問題をどのように解決しているのか疑問に思いますか? – rjoshi

+1

rjoshi、私はいくつかの技術的な詳細と別個の質問としてそれを求めるだろうが、それはあなたが本当にグローバルである必要はないと私には思われる。それをJNDIに入れ、与えられたルックアップが2回起こった場合、それもそれです。 – Yishai

+0

@Yishai:thx。あなたの提案のために。私はそれを試し、あなたに知らせるでしょう。私はJNDI/EJBラッパーを避け、クラスローダーのハックを使って解決しようとしていましたが、それが唯一の方法だと思います。 – rjoshi

0

TRUE Singletonを達成するために、あなたはガイドラインの下に従っています:

  1. finalとして、あなたのクラスを作成します。他の人はそれサブクラスすることができず、
  2. 1つの以上のインスタンスを作成しますprivate static final
  3. として、あなたのシングルトンインスタンスを作成しprivate constructorpublic getInstance()方法を提供します。
  4. このSingletonクラスはone ClassLoader only
  5. オーバーライド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の質問以下を参照してください。

What is an efficient way to implement a singleton pattern in Java?

関連する問題