スプリングシングルトンが複数回作成されました

私は私の春のWebアプリケーションで定義されたBeanを持っていて、このBeanのインスタンスを1つしか持たないことを期待しています。私のBeanの定義は次のとおりです。


AccessControlのコンストラクタでは、次のような識別子をオブジェクトに割り当てます。

public class AccessControl {
   private long id = 0;
   public AccessControl() {
        id = System.currentTimeMillis();
   }

   public long getAccessControlId() {
        return id;
   }
}

別のクラスでは、次のようなAccessControlのインスタンスを取得しようとします。

            ApplicationContext ctx =
                     new ClassPathXmlApplicationContext("acbean.xml");

            AccessControl ac = (AccessControl) ctx.getBean("accessControl");
            LOGGER_.info("AccessControl Identifier : " + ac.getAccessControlId());

"id"の値がコンストラクタで設定され、コンストラクタが何度も呼び出されるべきではないため、同じ値になることを期待していますが、これはまさに起こっていることです。実際には、コンストラクタにlog文を追加し、毎回新しいオブジェクトを作成します。

私は読んだ: http: //www.digizenstudio.com/blog/2006/09/14/a-spring-singleton-is-not-a-singleton/ 2つの異なるBean識別子で2回定義された同じクラスを処理しているとは思わないし、アプリケーションのコンテキストも同じです。

誰かが私がBeanを定義した方法で間違っていることを共有できますか?

私はまた、singleton = "true"とscope = "singleton"を実験しましたが、何の違いもありません。

ありがとう。

6
getBean()を呼び出すたびにコンストラクタが2回または1回呼び出されますか?
追加された 著者 Tomasz Nurkiewicz,
main メソッドのこの部分は、何度も繰り返し実行されていますか?この場合、毎回異なる値が得られます。実行するたびに新しいJVMを作成するためです。オブジェクトは、JVMのインスタンスの外部には存続しません。それはあなた自身で行う必要のあるものです(おそらくデータベースで)。
追加された 著者 nicholas.hauschild,
残念ながら、私はその答えを知らない。ドキュメントによれば、それは私に何度も同じオブジェクトを与えなければなりません。つまり、初めてコンストラクタを呼び出すべきではないということです。私が見たものに基づいて、 "getBean(...)"を呼び出すたびにコンストラクタが呼び出されています。これは、ドキュメンテーションが言うものとまったく反対です
追加された 著者 user305210,
そのWebアプリケーションであり、アプリケーションが再起動されない限り、新しいJVMインスタンスは画像に入ってはいけません
追加された 著者 user305210,

3 答え

春のシングルトンはアプリケーションコンテキストごとにあります。アプリケーションコンテキストの新しいインスタンス(2番目のコードサンプルの最初の行など)を作成するたびに、すべてのシングルトンがインスタンス化されます。

単一のアプリケーションコンテキストを用意し、アプリケーション内で再利用する必要があります

16
追加された
はい、それは間違いです。私はまだあなたのソリューションを試していないが、これは問題を作成していることを100%としている。ありがとう。
追加された 著者 user305210,

次の呼び出しごとに新しいアプリケーションコンテキストを作成しています。

ApplicationContext ctx = new ClassPathXmlApplicationContext("acbean.xml");

したがって、新しい春のコンテナになります。つまり、新しいコンテナによって豆がすべて再作成されます。

また、あなたはWebアプリケーションでこれを持っていたと述べました。その場合は、WebアプリケーションにSpringコンテキストをロードさせ、必要に応じてそのコンテキストを取得して使用する必要があります。

web.xmlに追加:


    Core Spring context.
    contextConfigLocation
    /WEB-INF/classes/applicationContext.xml


    Spring loader.
    org.springframework.web.context.ContextLoaderListener

または同様のもの。必要に応じてサーブレットコンテキストを介してWebコンテキストを取得します。

もう1つの注意点:バネの1つのポイントは、制御の反転を提供することです。通常、依存性注入を使用します。コンテキストを取得して自分でBeanを引っ張るのではなく、Springが依存関係を注入することを許可することを考慮する必要があります。

7
追加された
これありがとう。私はこのアプローチに気づいていませんでしたが、私は同じようなものを探していました。
追加された 著者 user305210,

Springアプリケーションでは、自分のアプリケーションコンテキストを明示的に作成するべきではありません。

理想的には、シングルトンをクラスに注入するか、 ApplicationContextAwareドキュメントいくつかの注意事項)。私は注射を好む。より簡単に。

2
追加された