@ModelAttribute の動き
- @ModelAttribute アノテーションは、コントローラのメソッドか、引数につけて使う。
- いずれの場合も、ハンドラメソッドが動く前にアノテーションが検出され、メソッドについているか、引数についているかに応じて、Spring によって処理される。
- メソッドについている場合
- Spring がハンドラメソッドを呼ぶ前に、@ModelAttribute つきのメソッドを呼び出す。
- Spring は、その戻り値を Model に詰める。
- Model に詰める際のキー (名前) は、@ModelAttribute.name or value で指定する。未指定の場合は戻り値のオブジェクトのクラス名から自動生成されたものになる。
- 引数についている場合
- Spring がハンドラメソッドを呼ぶ前に、その引数につけられた @ModelAttribute.name or value に対応するオブジェクトを Model から探す。省略した場合は、クラス名から Spring が自動的に決定する。Model に該当するオブジェクトがなければ、そのタイミングで new する。
- 引数のオブジェクトが用意できたら、Spring はそのオブジェクトに対してリクエストボディのバインディングを行う。リクエストパラメータの名前と一致するオブジェクトのメンバフィールドに対して値がバインドされる。リクエストパラメータに含まれない値に対しては何も行わない。
- そうして用意されたオブジェクトが、ハンドラメソッドのオブジェクトとして渡される。
- バインディングを行いたくない場合は @ModelAttribute.binding に false を設定する。
- @SessionAttributeによってセッション値を引数で受け取る場合、項1で受け取ったオブジェクトが項2のバイディング処理でメンバフィールドが上書きされる場合がある。バイディングはリクエストパラメータの名前とメンバフィールド名の一致で行われるため。そのため、セッション値を引数で受け取る場合、@ModelAttribute.binding に false を設定しておく。
- ModelAttributeの記述の省略について、アノテーションを記述しなくても同じ動作になります。省略された場合、Spring MVCは、クラス名の先頭を小文字にした名前をモデル名とみなして引数に渡そうとします。この省略は便利ですが、同じクラスを別々のモデルとして扱いたいときには注意が必要です。
参考
Spring がリクエストパラメータを処理する流れを理解したい