加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

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

发布时间:2020-12-16 09:20:47 所属栏目:安全 来源:网络整理
导读:我一直在 Scala使用 Play! Framework近一年.我目前使用版本 2.5.x. 我知道Play中控制器的发展,以及开发人员被迫离开静态对象路由. 我也知道Guice的使用情况. 如果您下载activator并运行: activator new my-test-app play-scala Activator将为您生成一个模板



我一直在 Scala使用 Play! Framework近一年.我目前使用版本 2.5.x.

我知道Play中控制器的发展,以及开发人员被迫离开静态对象路由.

我也知道Guice的使用情况.

如果您下载activator并运行:

activator new my-test-app play-scala

Activator将为您生成一个模板项目.
我的问题具体是关于该模板的this文件.

我的测试,应用程序/应用程序/服务/ 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()
}

您还可以在this文件中看到它的用法:

我的测试,应用程序/应用/控制器/ 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相同的实例.

所以我的问题是:

为什么使用@Singleton然后@Inject它进入一个控制器,在这个例子你可以只使用一个Scala对象?
它的代码少了很多.

例:

我的测试,应用程序/应用程序/服务/ Counter.scala

package services

trait ACounter {
  def nextCount: Int
}

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

使用它像这样:

我的测试,应用程序/应用/控制器/ 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) }

}

有什么不同?注射是首选,为什么?

解决方法

注射是首选吗?一般是的

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

>控制器与Counter的具体实现分离.

>如果要使用对象,则必须更改控制器以指向不同的实现. EG Counter2.nextCount().toString

>您可以使用Guice自定义绑定来更改测试期间的实现

>让我们说,在Counter里面你正在做一个WS调用.这可能会导致单元测试困难.如果您使用Guice进行依赖注入,则可以覆盖Counter和AtomicCounter之间的绑定,以指向专门针对测试编写的脱机版Counter.有关使用Guice进行测试的更多信息,请参阅here.

另请参阅Play已经迁移到DI的motivations.

我一般说,因为我看到依赖注入使用Spring和其他Java框架非常错误.我会说你应该使用自己的判断,但是错误地使用DI for Play.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读