Guice DI是否每次都创建一个新的WSClient实例

Does Guice DI create a new WSClient instance everytime

我有一个客户端 class 向外部供应商发出 API 调用。在我的控制器中,我按如下方式注入客户端。

@Singleton
class AdsController @Inject()(client: MyClient)(
  implicit ec: ExecutionContext
) extends InjectedController {

  def index = Action.async(json.parse[ClientRequest])  {
     client.send(request.body).map({
       case s: SuccessResponse => Ok(Json.toJson(s))
       ...
     }) 
  }
}

客户端class如下所示


class MyClient @Inject()(ws: WSClient, appConfig: Configuration)
(implicit ec: ExecutionContext) {...}

我想了解两件事

  1. 注入器是否为每个请求注入一个新的 MyClient 实例?
  2. 如果是,注入器是否每次都注入一个新的 WSClient 和 Configuration 实例?

如果两者都是肯定的,那么注入配置会不必要地创建新实例,这不是一个好主意。

默认情况下,Guice 总是创建一个新实例。除非您将其配置为通过例如重用实例将对象注释为 @singleton 或配置使用某些缓存的 Provider 或使用 bind 明确指向在需要某些 class 时应使用的实例..

这是一种理想的行为,因为存在许多与使用单例相关的问题和错误(例如,使用它们更容易产生内存泄漏),因此这必须是程序员有意识的、明确的决定,谁应该确保它不会咬到他们。

Play 中的路由器是 singleton

@Singleton
class RoutesProvider @Inject() (
    injector: Injector,
    environment: Environment,
    configuration: Configuration,
    httpConfig: HttpConfiguration
) extends Provider[Router] {

...

bind[Router].toProvider[RoutesProvider]

这实际上意味着即使控制器 class 没有用 @Singleton 注释,注入的控制器实例在请求之间是 ,除非路由以 @ 运算符为前缀在 routes:

...if you prefix a controller with @ ... a new action instantiated per request.

例如,给定

class MyClient

class HomeController @Inject()(cc: ControllerComponents, client: MyClient) extends AbstractController(cc) {
  def index = Action {
    Ok(s"HomeController identity = ${this.hashCode}\nMyClient identity = ${client.hashCode}")
  }
}

和以下 routes 文件

GET     /                           controllers.HomeController.index

不同的请求总是return相同的身份,尽管HomeController不是单身人士

// request 1
HomeController identity = 409392943
MyClient identity = 475611387

// request 2
HomeController identity = 409392943
MyClient identity = 475611387

但是如果我们在路由文件中使用 @ 运算符

GET     /                           @controllers.HomeController.index

然后我们看到每个新请求的身份都在变化:

// request 1
HomeController identity = 1249276649
MyClient identity = 1152488919

// request 2
HomeController identity = 41809453
MyClient identity = 213518354