です。
この文は紛らわしいものです。前者は(スコープ)プロキシとして定義されていない限り、シングルトンスコープ豆 にセッションスコープの豆を注入することができない
ばねとして言い換えなければなりません。
つまり、Springは非プロキシのセッションスコープBeanをシングルトンスコープのBeanに挿入することができません。これは、シングルトンスコープのBeanにプロキシされたセッションスコープBeanをインジェクトするのに成功します。
同じユーザーが同じ アプリケーションで同時に有効なセッションを持つと仮定すると、ScopedProxyはどのようなセッションを意味するのでしょうか?
明確にする最初のものはセッションがHttpSession
で表されるサーブレットコンテナの構成要素であるということです。 Spring(およびSpring MVC)は、セッションスコープのBean(およびFlash属性などのその他のもの)で抽象化します。
HttpSession
オブジェクトは通常、適切なクッキーによってユーザーに関連付けられます。 HTTPリクエストはCookieにユーザ識別値を提供し、サーブレットコンテナは関連付けられたHttpSession
を取得または作成します。換言すれば、セッションは要求内の情報から識別可能である。あなたまたはSpringはリクエストにアクセスする必要があります。
Spring MVCは通常、ハンドラメソッドに公開されていなくても、明らかにDispatcherServlet
を通してリクエストにアクセスできます(Spring MVCがあなたからサーブレットAPIを隠そうとすることに注意してください)。
以下は、多少の実装の詳細です。 Spring MVCは、要求オブジェクト(HttpServletRequest
)を呼び出しスタックの上まで伝播する代わりに、RequestContextHolder
に格納します。
Holderクラスはスレッドバウンド RequestAttributes
オブジェクトの形式でWeb要求を露出させます。
これは、サーブレットコンテナ(つまり、非同期非同期)が1つのスレッドで要求を処理するため、これを行うことができます。そのリクエストハンドラスレッドでコードを実行している場合は、そのリクエストにアクセスできます。リクエストにアクセスできる場合はyou have access to the HttpSession
です。
実際の実装はかなり長いです。あなたがそれに入るには、SessionScope
で始まり、あなたの方法を働かせます。
これは具体的なBean型のオブジェクトをSpringに注入しないと、プロキシを注入します。次の例では、JDK proxies(インターフェイスのみ)を使用して、セッションスコープのプロキシの動作を示します。
interface SessionScopedBean {...}
class SessionScopedBeanImpl implements SessionScopedBean {...}
考えると春が
SessionScopedBean proxy = (SessionScopedBean) Proxy.newProxyInstance(Sample.class.getClassLoader(),
new Class<?>[] { SessionScopedBean.class }, new InvocationHandler() {
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
HttpSession session = ...;// get session through RequestContextHolder
SessionScopedBean actual = session.getAttribute("some.bean.identifier");
if (actual == null) {
// if absent, set it
session.setAttribute("some.bean.identifier", actual = new SessionScopedBeanImpl());
}
return method.invoke(actual, args); // delegate to actual object
}
});
と同様に(しかし、はるかに洗練された)プロキシSessionScopedBean
を作成し、あなたのシングルトン豆(おそらくコントローラ)にこのproxy
オブジェクトを注入します。シングルトンBeanがセッションスコープのBeanを使用しようとしているとき、実際にはプロキシを経由しており、プロキシは実際のオブジェクトを取得してその呼び出しを委譲しています。
セッションが0人の場合はどうなりますか? NullPointerException
は発生しますか?
春にプロキシが挿入されます。プロキシはnull
ではありません。それはオブジェクトです。実際のターゲットを取得して使用する方法を知っています。セッションスコープでは、ターゲットが存在しない場合は、作成されてセッションに保存されてから使用されます。
ここで危険なのは、セッションのコンテキスト外でセッションスコープのプロキシを使用することです。前述のように、Servletコンテナは単一のスレッド内で単一の要求を処理することで動作します。要求がバインドされていないスレッドでセッションスコープのBeanにアクセスしようとすると、例外が発生します。
このように、セッションスコープのBeanをスレッドの境界を超えて渡そうとしないでください。 Servlet仕様では、Async ProcessingとSpring MVC supports itをDefferedResult
とCallable
と使用できます。それについてのブログシリーズ、hereがあります。セッションスコープのBeanを渡すことはできません。ただし、AsyncContext
への参照がある場合は、HttpServletRequest
を取得してHttpSession
にアクセスすることができます。
スレッドをディスパッチする方法(またはRunnable
)を制御する場合は、要求コンテキストlike the one described hereをコピーするためのテクニックがあります。ここで
は(セッション)スコープやプロキシに関するいくつかの関連記事です:
親愛なるdownvoter、あなたは悪いことを説明することができる質問に属していますか?私はそれをより適切な形に書き直すかもしれません。 –