ControllerComponents の中身を少し見てみる

PlayFrameworkを使っていると、まるで呪文のように何も考えずにControllerに書いている、これ。

class HomeController @Inject() (
    cc: ControllerComponents
)(implicit ec: ExecutionContext)
    extends AbstractController(cc) {

この、ControllerComponentsAbstractController が何かよく分からずに使っている。まるでJava習いたての、 public static void main(String args[]) {...} のよう。

眺めていてもよく分からないので、実装(Github)を追ってみる。

/**
 * The base controller components dependencies that most controllers rely on.
 */
trait ControllerComponents {
  def actionBuilder: ActionBuilder[Request, AnyContent]
  def parsers: PlayBodyParsers
  def messagesApi: MessagesApi
  def langs: Langs
  def fileMimeTypes: FileMimeTypes
  def executionContext: scala.concurrent.ExecutionContext
}

見ると、ControllerComponents は 下記をとる trait のよう。

  • ActionBuilder[Request, AnyContent]
  • PlayBodyParsers
  • MessagesApi
  • Langs
  • FileMimeTypes
  • ExecutionContext

PlayBodyParsersExecutionContext は見たことあるなぁって程度で他はよく知らない。ちなみに公式のAPIドキュメント

次に上記の ControllerComponents を渡している AbstractControllerGitHub, 公式API

/**
 * An abstract implementation of BaseController to make it slightly easier to use.
 */
abstract class AbstractController(protected val controllerComponents: ControllerComponents) extends BaseController

AbstractControllerBaseController を継承し、ControllerComponents をプロパティとして外部から受け取とるといった感じの模様。次に、BaseController を見てみる。

trait BaseController extends BaseControllerHelpers {

  /**
   * The default ActionBuilder. Used to construct an action, for example:
   *
   * {{{
   *   def foo(query: String) = Action {
   *     Ok
   *   }
   * }}}
   *
   * This is meant to be a replacement for the now-deprecated Action object, and can be used in the same way.
   */
  def Action: ActionBuilder[Request, AnyContent] = controllerComponents.actionBuilder
}

BaseControllerAction: ActionBuilder[Request, AnyContent] を持つみたい。さっきの、ControllerComponents がここでおそらく渡されるのだろう。ちなみに右辺の controllerComponetnsBaseControllerHelpers trait のプロパティ。

んー。。今一掴めない。。とりあえずは、

  1. Inject された、ControllerComponentsAbstractController に渡される。
  2. AbstractControllerBaseController を継承している。
  3. BaseController は trait、BaseControllerHelpers を継承しており、これがコンテキスト中にある ControllerComponents の実体を利用している。

って流れなんだろう。

ちょっとまだふわっとしているので、また時が経ったら見直してみようと思う。