began.2015-10-01SpringのSingletonな管理Beanに、自分より短いライフサイクルのBeanをDIしようとすると?Springなんとなく結果が見えている気がするんですけど、確認という意味で試してみました的な。SpringのBeanってデフォルトのスコープはSingletonですが、SingletonなBeanに対してそれより短いライフサイクル(例えば、RequestやSession)のものを放り込もうとするとどうなるか?という話。MVCを使って試してみます。確認用のコードは、こんな感じ。アプリケーションのエントリポイント。ScopeなService。}}処理をしているのがどのスレッドかわかりやすいように、スレッドの名前を出力するようにしています。ScopeなService。}}各ServiceをDIするRestController。}}これらのクラスを使って、確認してみます。起動してみるとりあえず、アプリケーションを起動してみましょう。spring-boot:run結果、失敗します。org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:118)SingletonにAutowiredしようとしてるよ?ムリだから、みたいな感じですね。DI先のBeanがSingletonなのでそりゃそうだ的な。これで動いてもらっても困りますね。動かすには?これで終わっても面白くないので、このコードを動かすようにするにはどうしたらいいか、ちょっと考えてみます。Scopeにする最初に思いつきそうな方法。RestControllerのScopeを、Requestにします。{もちろん、これでも起動します。ScopeなBeanにProxyModeを設定する別解。例外のメッセージにも出ていましたが、ProxyModeを変更してみます。ここでは、ScopedProxyMode.TARGET_CLASSとしています。{この方法でも、動作するようになります。今回は、動作確認してみます。2つのコンソールから、curlを使って確認しましょう。※sleepが10秒入っているので、2つのリクエストに対する処理が時間的に重なり合うことになります。http://localhost:8080/request結果。2015-10-01T23:22:34.710それぞれのスレッドで、結果が混ざったりしていませんね。同じスレッドの名前のものだけが、同じ値になっています。http://localhost:8080/session結果。Scopeなので、Cookieの値を保持していれば次にリクエストを投げても同じ結果が得られます。ProxyModeを変えた場合には、どうなっているのか?ScopedProxyMode.TARGET_CLASSの説明にもありますが、CGLIBによる拡張が行われています。}スタックトレースを見ると、間にCGLIBが挟まっています。org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:717)ScopedProxyMode.INTERFACESを選択した場合は、JDKのProxyを使用して、インターフェースに対して動的な拡張が行われるようです。一応、くらいの気持ちで確認してみましたが、確認しておいてよかったです。読者になる検索リンクはてなブログブログをはじめる週刊はてなブログはてなブログPro月別アーカイブはてなブログをはじめよう!Kazuhiraさんは、はてなブログを使っています。ブログを報告するスターをつけました引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。