web-dev-qa-db-ja.com

静的(グローバル)シングルトンを注入するスプリング

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

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(beans)を構成しようとしています。私の推測では、単一のConfigurator Beanを次のように定義できます(または類似の何か)。

<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"を設定するのは正しいですか、それとも問題ありませんか?静的プロパティを正しく設定していますか?ここで私がやるべきことや考慮すべきことは他にありますか?前もって感謝します。

11
user1768830

Beanはデフォルトでシングルトンです。あなたは春のウェブサイトを介してこの/詳細情報を見つけることができます。

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

2
Bob Flannigon

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

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

ちなみに、これはスレッドセーフではありません:

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 も参照してください。

0
Dennis Löhmann