为什么要在Play Framework中的Scala对象上使用@Singleton?

Rhys Bradbury:

我一直在使用Play!Scala 框架已有近一年的历史了。我目前使用的版本2.5.X

我知道Play控制器的发展,以及开发人员如何被迫摆脱静态object路线。

我也知道Guice在游戏中的用法。

如果您下载激活器并运行:

activator new my-test-app play-scala

激活器将为您生成一个模板项目。我的问题是专门围绕该模板的文件。

my-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()
}

您还可以在文件中查看其用法

my-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) }

}

这意味着每个具有构造函数的控制器都@Inject() (counter: Counter)将接收的相同实例Counter

所以我的问题是:

为什么在本例中只能使用Scala对象@Singleton,然后再将@Inject其用作控制器?
它的代码少得多。

例:

my-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()
}

像这样使用它:

my-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) }

}

有什么区别?是首选注射剂,为什么?

nattyddubbs:

注射是首选方法吗?一般是

使用依赖注入的几个优点:

  1. 从控制器的具体实现中解耦控制器Counter
    • 如果要使用object,则必须更改控制器以指向其他实现。例如Counter2.nextCount().toString
  2. 您可以使用Guice自定义绑定在测试过程中更改实现
    • 可以说Counter内部正在WS通话。这可能会导致单元测试有些困难。如果在Guice中使用依赖项注入,则可以覆盖之间的绑定,CounterAtomicCounter指向Counter您专门为测试编写的脱机版本有关使用Guice for Play测试的更多信息,请参见此处

另请参阅Play迁移到DI 动机

我之所以这么说是因为我已经看到使用Spring和其他Java框架进行依赖注入会导致严重的错误。我想说您应该使用自己的判断,但在使用DI进行播放方面会犯错。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

为什么要在小对象上同步?

来自分类Java

为什么要在Java / Spring上使用Scala / Lift?

来自分类Java

为什么要在堆栈上使用Deque?

来自分类Dev

为什么要在pbuilder上使用sbuild?

来自分类Dev

为什么要在memset上使用bzero?

来自分类Dev

为什么要在Dict上使用HashDict?

来自分类Dev

为什么要在冻结的对象上使用Object#clone?

来自分类Dev

为什么要在主线程上订阅?

来自分类Dev

为什么要在AngularJS中使用$ onInit?

来自分类Dev

为什么要在golang中使用组合?

来自分类Java

为什么要在Android中使用RequestQueue?

来自分类Dev

为什么要在Dialogflow中使用动作

来自分类Dev

为什么要在结构中使用malloc?

来自分类Dev

为什么要在FRP中使用行为

来自分类Dev

为什么要在延迟中使用setTimeout

来自分类Dev

为什么要在Flux中使用“动作”?

来自分类Dev

为什么要在laravel中使用npm?

来自分类Dev

为什么要在命令前使用env?

来自分类Dev

为什么要在Flink中使用kafka

来自分类Dev

为什么要在Typescript中使用接口

来自分类Dev

为什么要在ListView中使用DataTemplate?

来自分类Dev

为什么要在函数的参数中赋值?

来自分类Python

为什么要在Python中关闭文件?

来自分类Dev

为什么要在init()中检查nil

来自分类Dev

为什么要在RabbitMQ中声明交换?

来自分类Dev

为什么需要在结构中填充?

来自分类Dev

什么是gvfs,为什么要在我的系统上使用它?

来自分类Dev

JVM为什么要在内存中重定位对象?

来自分类Dev

为什么要在变量中存储Promise对象?

Related 相关文章

热门标签

归档