12

私は次のようなクラスを持っています:

public class Configurator {
    private static Configurator INSTANCE = null;

    private int maxRange = 1;

    // many other properties; each property has a default value

    private static synchronized Configurator getInstance() {
        if(INSTANCE == null)
            return new Configurator();

        return INSTANCE;
    }

    public static int getMaxRange() {
        getInstance().maxRange;
    }

    public static void setMaxRange(int range) {
        getInstance().maxRange = range;
    }

    // Getters and setters for all properties follow this pattern
}

これは、アプリの起動時に設定できるグローバル構成オブジェクトとして機能し、プロジェクト全体で数十のクラスで使用されます。

// Called at app startup to configure everything
public class AppRunner {
    Configurator.setMaxRange(30);
}

// Example of Configurator being used by another class
public class WidgetFactory {
    public void doSomething() {
        if(Configurator.getMaxRange() < 50)
            // do A
        else
            // do B
    }
}

現在、このコードを Spring プロジェクトにインポートしており、Sprinig XML (Bean) を構成しようとしています。私の推測では、孤独なConfiguratorBean を次のように (または同様の方法で)定義できると思います。

<bean id="configurator" class="com.me.myapp.Configurator" scope="singleton">
    <property name="maxRange" value="30"/>
    <!-- etc., for all properties -->
</bean>

そうWidgetFactory#doSomethingすれば、実行時に、Spring はすでにConfiguratorクラスをロードして事前に構成しています。

を設定するのは正しいですscope="singleton"か、それとも問題ではありませんか? 静的プロパティを正しく設定していますか? ここで行う必要がある、または考慮する必要があることは他にありますか? 前もって感謝します。

4

4 に答える 4

11

デザインパターンとしての Singleton と Spring の singleton 機能にはいくつかの違いがあります。設計パターンとしてシングルトンを使用すると、クラス ローダーごとにクラスのオブジェクトが 1 つ定義されます。対照的に、Spring のシングルトン機能 (およびアプローチ) は、Spring コンテキストごとに 1 つのインスタンスを定義します。

この場合getInstance()、Spring が使用するメソッドを利用して、オブジェクト インスタンスを取得できます。

<bean id="configurator" class="com.me.myapp.Configurator" factory-method="getInstance">
</bean>

Spring ではsingletonBean スコープがデフォルトであるため、定義する必要はありません。

Spring Bean として使用する場合は、それをつかむためにconfigurator使用するのではなく、他のオブジェクトに注入する必要があります。getInstance()したがって、他の Spring Bean では @Autowired を使用するか、xml ファイルを介して Bean への参照を定義します。他のクラスでの使用を再編成しない場合configurator、違いはありません。Spring はクラスをインスタンス化しますが、以前と同じように使用します。

また、シングルトンの設計に誤りがあることもわかりました。getInstance()メソッドはパブリックにする必要があり、他のメソッドは静的であってはなりません。使用した例では、次のように Singleton を使用する必要があります。

Configurator.getInstance().someMethod()

この場合、オブジェクトをインスタンス化せずに、実際には Singleton クラスを使用するだけです! Singleton 設計パターンとその使用方法の詳細については、Singleton のウィキペディア (Java の例を含む) を参照してください


注:シングルトンとして使用Configuratorし、Spring のシングルトン機能を利用することを知って、試してみる価値があります。これを行うと、次のことができるという利点があります。

  • getInstance()メソッドを削除します
  • コンストラクターを公開する
  • Spring にその単一のオブジェクトをインスタンス化させます。
于 2013-02-01T11:25:05.240 に答える
2

Bean はデフォルトでシングルトンです。これ/詳細については、春の Web サイトで確認できます。

getInstance で新しい Configurator をインスタンス化しないでください。これは、Spring Loaded Bean を参照せず、重大な問題が発生する可能性があるためです。この Bean を配線してからそのままにしておくことができます。配線したため、null にはなりません (そうであれば、プログラムは初期化に失敗します)。

于 2013-02-01T11:15:50.840 に答える
0

ところで: これはスレッドセーフではありません:

if(INSTANCE == null)
        return new Configurator();

    return INSTANCE;
}

一方、これは次のようになります。

private static Configurator INSTANCE = new Configurator();

(熱心な初期化)

private static volatile Singleton _instance = null;

(volatile キーワードによる遅延初期化)

これは、Java がメモリを割り当ててインスタンスを作成する方法に関係しています。これはアトミックではありませんが、2 つのステップで実行され、スレッド スケジューラによって干渉される可能性があります。

http://regrecall.blogspot.de/2012/05/java-singleton-pattern-thread-safe.htmlも参照してください。

于 2015-10-11T11:23:52.393 に答える
0

はい、グローバルなものが必要な場合は、シングルトン スコープが適切なオプションです。ここで言及する価値のあるいくつかのことは次のとおりです。

  1. Spring のデフォルト スコープはシングルトンであるため、Bean をシングルトン スコープとして明示的に設定する必要はありません。
  2. Spring を使用すると、プライベート インスタンスやファクトリ メソッドなどのシングルトン パターンスタイルのコードを記述する必要がなくなります。これは、Spring コンテナーごとに 1 つのインスタンスのみが存在することを Spring が保証するためです。言うまでもなく、ファクトリ メソッドは非公開です。
于 2013-02-01T11:21:08.013 に答える