如何在Scala中将参数注入类/特征方法 [英] How to inject parameters into a class/trait method in Scala
问题描述
我在我的Play Scala(2.5x,2.11.11)应用程序中有一个代码,到目前为止该代码一直运行良好(它基于以下链接:
I have a code in my Play Scala (2.5x, 2.11.11) app which has been running just fine so far (it is based on the following link: https://fizzylogic.nl/2016/11/27/authorize-access-to-your-play-application-using-action-builders-and-action-functions/). But now I need to pass another class instance to ApplicationAuthorizationHandler class (NOTE: throughout my code I am using Guice DI for injecting parameters into class constructors).
当前代码:
class ApplicationAuthorizationHandler
extends AuthorizationHandler {
...
}
trait AuthorizationHandler {
...
}
trait AuthorizationCheck {
def authorizationHandler: AuthorizationHandler = new ApplicationAuthorizationHandler
object AuthenticatedAction extends ActionBuilder[RequestWithPrincipal] {
override def invokeBlock[A](request: Request[A], block: (RequestWithPrincipal[A]) => Future[Result]): Future[Result] = {
def unauthorizedAction = authorizationHandler.unauthorized(RequestWithOptionalPrincipal(None, request))
def authorizedAction(principal: Principal) = block(RequestWithPrincipal(principal, request))
authorizationHandler.principal(request).fold(unauthorizedAction)(authorizedAction)
}
}
}
//Example controller using this trait AuthorizationCheck
class MyController @Inject() extends Controller with AuthorizationCheck {
def myAction = AuthenticatedAction { implicit request =>
...
}
所需代码:
class ApplicationAuthorizationHandler @Inject() (userService: UserService)
extends AuthorizationHandler {
...
// userService is used here
}
但是由于ApplicationAuthorizationHandler的实例是在特征AuthorizationCheck中实例化的,所以无法将UserService实例注入其中.我与所有控制器都具有Mixin这个特质,因此除非有更好的方法(并且必须存在),否则我希望保持相同的方式. 首先,有没有一种方法可以直接注入类/特征方法? 或者,有没有一种方法,我不实例化特性AuthorizationCheck中的ApplicationAuthorizationHandler并在运行时在控制器内部传递它? 还是其他方式?
But since the instance of ApplicationAuthorizationHandler is instantiated inside trait AuthorizationCheck I can't inject UserService instance into it. I am Mixin this trait with all controllers so would like to keep the same way unless there is a better way (and there must be). First, is there a way to inject directly into class/trait method ? Alternatively, is there a way where I don't instantiate ApplicationAuthorizationHandler in trait AuthorizationCheck and pass it during run-time inside the controller ? Or any other way ?
推荐答案
特质不需要提供实现,因此您可以使用以下内容:
A trait does not need to provide an implementation, so you can have something like:
trait AuthorizationHandler {
...
}
class ApplicationAuthorizationHandler extends AuthorizationHandler {
...
}
trait AuthorizationCheck {
// just declaring that implementations needs to provide a
def authorizationHandler: AuthorizationHandler
object AuthenticatedAction extends ActionBuilder[RequestWithPrincipal] {
override def invokeBlock[A](request: Request[A], block: (RequestWithPrincipal[A]) => Future[Result]): Future[Result] = {
def unauthorizedAction = authorizationHandler.unauthorized(RequestWithOptionalPrincipal(None, request))
def authorizedAction(principal: Principal) = block(RequestWithPrincipal(principal, request))
authorizationHandler.principal(request).fold(unauthorizedAction)(authorizedAction)
}
}
}
// So, now this controller needs to provide a concrete implementation
// of "authorizationHandler" as declared by "AuthorizationCheck".
// You can do it by injecting a "AuthorizationHandler" as a val with
// name authorizationHandler.
class MyController @Inject()(val authorizationHandler: AuthorizationHandler) extends Controller with AuthorizationCheck {
def myAction = AuthenticatedAction { implicit request =>
...
}
}
当然,您需要提供一个模块来将AuthorizationHandler
绑定到ApplicationAuthorizationHandler
:
And of course, you need to provide a module to bind AuthorizationHandler
to ApplicationAuthorizationHandler
:
import play.api.inject._
class AuthorizationHandlerModule extends SimpleModule(
bind[AuthorizationHandler].to[ApplicationAuthorizationHandler]
)
当然,ApplicationAuthorizationHandler
可以注入自己的依赖项.您可以在我们的文档中查看更多详细信息.
Of course, ApplicationAuthorizationHandler
can have its own dependencies injected. You can see more details at our docs.
这篇关于如何在Scala中将参数注入类/特征方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!