4

Spring Event を使用して、Web アプリケーションで自分の Bean と「会話」したいと考えています。

たとえば、イベントを発生させる Bean は次のようになります。

@Controller
@Scope("request")
@KeepAlive
public class Controller extends InitializingBean, ApplicationEventPublisherAware {

private ApplicationEventPublisher applicationEventPublisher;    

public void test() {
  applicationEventPublisher.publishEvent(new TestEvent(this));
}

}

そして、私のリスナーイベントは次のようなものです:

@Component
@Scope("request")
@KeepAlive
public class Module implements ApplicationListener<TestEvent> {

    @Override
    public void onApplicationEvent(TestEvent event) {

    }

}

最も重要な点は、ページが呼び出されるたびに初期化する必要があるため、これらの Bean はスコープ リクエストであるということです。

しかし、起動時に次のメッセージが表示されます。

原因: java.lang.IllegalStateException: スレッドにバインドされた要求が見つかりません: 実際の Web 要求の外部で要求属性を参照していますか、または元の受信スレッドの外部で要求を処理していますか? 実際に Web リクエスト内で操作していてもこのメッセージが表示される場合、コードは DispatcherServlet/DispatcherPortlet の外部で実行されている可能性があります。この場合、RequestContextListener または RequestContextFilter を使用して現在のリクエストを公開します。

たとえば、Spring が起動時にモジュール Bean をインスタンス化しようとした場合、Bean はスコープ リクエストであるため、これを行うことはできません (コンテキスト リクエストはインスタンス化されません)。

イベント管理を削除すると、すべて正常に動作します。

だから、私の質問は:

イベントリスナーをスコープリクエストにすることは可能ですか? そして、これを行う方法は?

ありがとう

4

1 に答える 1

1

TestEvent を処理するために、Singleton ApplicationListener にスコープ プロキシを挿入してみてください。

@Scope(proxyMode=ScopedProxyMode.TARGET_CLASS, value="request")
public class TestEventHandler {

    public void onTestEvent(TestEvent event) 
        // ...  
    }

}
  public class TestEventApplicationListener implements ApplicationListener<TestEvent> {

    @Autowired
    private TestEventHandler handler;

    @Override
    public void onApplicationEvent(TestEvent event) {

        handler.onTestEvent(event);

    }
}
于 2013-02-15T14:23:29.567 に答える