私はあなたに2つのクラスがあると仮定します。まず、あなたのClient
クラスを持っています。そして、
@Singleton // this is not necessary, I put it here so you know this is possible
class Client @Inject() (ws:WSClient, baseUrl: String) {
// Since this controller is not annotated with @Inject
// it WILL NOT be used when binding components
def this(ws:WSClient) = this(ws, "<url string>")
def getResponse() = {
// do something using ws object
}
}
お持ち、コントローラインスタンスごとに、Client
を使用して別のクラス:
class MyController @Inject() (client: Client) extends Controller {
def someAction = Action {
// do something with client object
}
}
ここでの主なポイントは、コントローラを作成する必要はありませんでしたということですa Client
インスタンス。それはGuiceによって自動的に注入されました。
また、クライアントクラスにはbaseUrl
が必要で、そこにはどの値が必要かをプレイに伝える場所はありません。これは、あなたがこのような何かができるより設定の場合:あなた本当にがにあなたのClient
オブジェクトがString
を受けたい場合は、
import play.api.Configuration
class Client @Inject() (ws:WSClient, configuration: Configuration) {
def getResponse() = {
val baseUrl = configuration.getString("key.to.baseUrl")
// do something using ws object and baseUrl
}
}
をしかし、我々はtell Play which String needs to be injectedする必要があります。
package com.acme.modules
import com.google.inject.AbstractModule
import com.google.inject.name.Names
class MyModule extends AbstractModule {
def configure() = {
bind(classOf[String])
.annotatedWith(Names.named("baseUrl")) // attention to the name here. It will be used below
.toInstance("http://api.example.com/")
}
}
次に、このモジュールを有効にするには、application.conf
に
play.modules.enabled += "com.acme.modules.MyModule"
質問の編集後
import play.api.Configuration
// @Named needs to receive the same value defined at the module class.
class Client @Inject() (ws:WSClient, @Named("baseUrl") baseUrl: String) {
def getResponse() = {
val baseUrl = configuration.getString("key.to.baseUrl")
// do something using ws object and baseUrl
}
}
更新:
Controller Action --> Determine Plugins to Execute --> Execute Plugins ---> Plugin1
:
は、あなたが/必要したい構造を与えるとその後
、我々はそれを期待しているString
どの程度具体的にはClient
を変更しますあなたのコードは、次のようなクラスでそのパスをたどることもできます:
MyController -> PluginResolver -> Plugin
-> PluginRunner ->
そして、そして、あなたが持つことができます。
コントローラー:
class MyController @Inject() (
pluginResolver: PluginResolver,
pluginRunner: PluginRunner
) extends Controller {
def action = Action {
val plugins = pluginsResolver.resolve(/* give a criteria to select plugins */)
val someResultFromPluginsExecution = pluginsRunner.run(plugins)
// map result from plugins execution to a play play.api.mvc.Result
// return the play.api.mvc.Result
}
}
プラグインクラス:
本当の魔法がここ
PluginResolver
で行わ
import play.api.inject.Injector
class PluginResolver @Inject()(injector: Injector) {
def resolve(/* some criteria to resolve plugins */): Seq[Plugin] = {
val pluginsClasses = ... // find the necessary plugins based on the criteria
pluginsClasses.map { pluginClass => injector.instanceOf(pluginClass) }
}
}
// ExecutionContext is not really necessary, but maybe you want/need
// another thread pool to execute plugins
class PluginRunner @Inject()(implicit executionContext: ExecutionContext) {
def run(plugins: Seq[Plugin]): Seq[PluginExecutionResult] = {
// run the plugins
// return the result
}
}
trait Plugin {
def execute(): PluginExecutionResult
}
。 play.api.inject.Injector
を使用してプラグインインスタンスを作成し、プラグインで依存性注入を使用できます。インスタンスごと:
class PluginThatNeedsWSClient @Inject(wsClient: WSClient) extends Plugin {
def execute(): PluginExecutionResult = {
// Use wsClient to call a remote service
// return the execution result
}
}
参考:
- Scala: Dependency Injection
- Scala: Play WS API
play.api.inject.Injector
警告が表示されているコードを表示します。 'WS'の代わりに' WSClient'を使用していますか? – marcospereira
新しいクライアント(WS.client)行に警告が表示されています。私の質問は、注入されたWSClient @marcospereiraを使用する方法です。 – konquestor
この呼び出し元は、プロジェクト内のテストまたは他の通常のクラスですか?依存関係注入を使って 'Client'を作成してバインドする理由はありますか? – marcospereira