1

Spring ベースの WebApp があります。私のアプリケーション コンテキストでは、次の Bean が定義されています。

<bean id="someSingleton" class="com.fake.SomeSingleton" scope="singleton"/>

1 つの Spring ディスパッチ サーブレット定義と、@Controllerこの Bean を自動配線したアノテーションを持つ 1 つのクラスがあり、Spring がこのクラスを一度だけインスタンス化することを期待しています。ただし、次のデバッグ コードによると、Spring はこのクラスを複数回インスタンス化しています。

private static final Semaphore SANITY_CHECK = new Semaphore(1);

public FakeSingleton(){
    if(!SANITY_CHECK.tryAcquire()){
      log.error("why?");
      System.exit(-1);
    else{
      log.error("OK");
    }
}

原因は何ですか?

注:春の3.1.2.RELEASEを使用しています

編集: 私が与えられたヒントのおかげで、私は犯人を見つけました.
DispatcherServlet とは別に、web.xml に ContextLoaderListener もありました。それを削除した後、SomeSingleton は 1 回だけインスタンス化されました。

<!-- Creates the Spring Container shared by all Servlets and Filters -->
<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<servlet>
    <servlet-name>FakeService</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/applicationContext.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>
4

2 に答える 2

2

考えられる理由はいくつかあります。

  • クラスはCGLIBプロキシによってラップされているため、コンストラクターは2回実行されます(@PostConstructコールバックは常にBeanごとに1回実行されます)。1回はクラス用で、もう1回はプロキシの継承用です。

  • より可能性が高いのは、BeanがメインコンテキストとSpringMVCコンテキストの2つのコンテキストによってピックアップされていることです。これは悪い習慣であり、避けるべきです。SomeSingletonクラスがいくつかのCLASSPATHスキャンを介してMVCディスパッチャーサーブレットコンテキストによって取得されていないかどうかを確認します。

ところで、このようなコードでは、のAtomicInteger代わりにsimpleを使用しても安全ですSemaphore

于 2012-11-12T18:47:51.540 に答える
1

シングルトンは、宇宙の熱死ごとではなく、コンテキストごとに 1 回です。

ロギングを有効にして、アプリ コンテキスト全体が複数回作成されている理由/場合を確認します。

于 2012-11-12T18:47:35.743 に答える