Warum mit @Singleton über Scala-Objekt im Play Framework?

Ich habe mit Spielen! Rahmen für Scala seit fast einem Jahr jetzt. Ich bin derzeit mit version 2.5.x.

Ich bin mir bewusst, die evolution des controllers in Spielen und wie die Entwickler waren gezwungen, Weg von statischen object Routen.

Ich bin mir auch bewusst, Guice Verwendung in spielen.

Wenn Sie den download Aktivator und ausführen:

activator new my-test-app play-scala

Aktivator erzeugt ein template Projekt für Sie.
Meine Frage ist, speziell rund um diese - Datei der Vorlage.

mein-test-app/app/services/Counter.scala

package services

import java.util.concurrent.atomic.AtomicInteger
import javax.inject._

/**
 * This trait demonstrates how to create a component that is injected
 * into a controller. The trait represents a counter that returns a
 * incremented number each time it is called.
 */
trait Counter {
  def nextCount(): Int
}

/**
 * This class is a concrete implementation of the [[Counter]] trait.
 * It is configured for Guice dependency injection in the [[Module]]
 * class.
 *
 * This class has a `Singleton` annotation because we need to make
 * sure we only use one counter per application. Without this
 * annotation we would get a new instance every time a [[Counter]] is
 * injected.
 */
@Singleton
class AtomicCounter extends Counter {  
  private val atomicCounter = new AtomicInteger()
  override def nextCount(): Int = atomicCounter.getAndIncrement()
}

Können Sie auch sehen, die Nutzung im diese Datei:

mein-test-app/app/controllers/CountController.scala

package controllers

import javax.inject._
import play.api._
import play.api.mvc._
import services.Counter

/**
 * This controller demonstrates how to use dependency injection to
 * bind a component into a controller class. The class creates an
 * `Action` that shows an incrementing count to users. The [[Counter]]
 * object is injected by the Guice dependency injection system.
 */
@Singleton
class CountController @Inject() (counter: Counter) extends Controller {

  /**
   * Create an action that responds with the [[Counter]]'s current
   * count. The result is plain text. This `Action` is mapped to
   * `GET /count` requests by an entry in the `routes` config file.
   */
  def count = Action { Ok(counter.nextCount().toString) }

}

Das bedeutet, dass jeder controller, hat der Konstruktor der @Inject() (counter: Counter) erhalten die gleiche Instanz von Counter.

Also meine Frage ist:

Warum @Singleton und dann @Inject ihn in einen controller, wenn für dieses Beispiel könnte man einfach ein Scala-Objekt?

Seine viel weniger code.

Beispiel:

mein-test-app/app/services/Counter.scala

package services

trait ACounter {
  def nextCount: Int
}

object Counter with ACounter {
  private val atomicCounter = new AtomicInteger()
  def nextCount(): Int = atomicCounter.getAndIncrement()
}

Verwenden Sie es wie so:

mein-test-app/app/controllers/CountController.scala

package controllers

import javax.inject._
import play.api._
import play.api.mvc._

import services.{Counter, ACounter}

/**
 * This controller demonstrates how to use dependency injection to
 * bind a component into a controller class. The class creates an
 * `Action` that shows an incrementing count to users. The [[Counter]]
 * object is injected by the Guice dependency injection system.
 */
@Singleton
class CountController extends Controller {
  //depend on abstractions
  val counter: ACounter = Counter

  def count = Action { Ok(counter.nextCount().toString) }

}

Was ist der Unterschied? Ist die Injektion bevorzugt, und warum?

  • Es wahrscheinlich egal, wenn Sie nicht brauchen, um Parameter an den controller. Aber wenn Sie das tun, dann muss es eine Klasse sein, die für guice zu instanziieren und injizieren der Abhängigkeiten.
Schreibe einen Kommentar