首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在编译时依赖注入中使用play.api.cache.Cache

在编译时依赖注入中使用play.api.cache.Cache
EN

Stack Overflow用户
提问于 2015-11-10 12:48:57
回答 2查看 918关注 0票数 4

我正在尝试将我的Play应用程序从2.3.9迁移到2.4.3,并使用编译时依赖注入。当我使用旧的全局缓存api对象( InstantiationException )时,我得到了一个play.api.cache.Cache。我已经在组件中包含了EhCacheComponents (它提供了一个缓存实现),但是看来Play试图直接实例化抽象CacheApi

代码语言:javascript
复制
play.api.http.HttpErrorHandlerExceptions$$anon$1: Execution exception[[InstantiationException: play.api.cache.CacheApi]]

<snip>

Caused by: java.lang.InstantiationException: play.api.cache.CacheApi
at java.lang.Class.newInstance(Class.java:427) ~[na:1.8.0_51]
at play.api.inject.NewInstanceInjector$.instanceOf(Injector.scala:49) ~[play_2.11-2.4.3.jar:2.4.3]
at play.api.inject.SimpleInjector$$anonfun$instanceOf$1.apply(Injector.scala:85) ~[play_2.11-2.4.3.jar:2.4.3]

我知道建议是使用新的依赖项注入组件,但是文档表明这仍然有效,我想让我的应用程序运行,而不必一蹴而就。

下面是一个简单的应用程序,它演示了这个问题:

代码语言:javascript
复制
class AppApplicationLoader extends ApplicationLoader {
  def load(context : play.api.ApplicationLoader.Context) : play.api.Application = {
    Logger.configure(context.environment)
    new AppComponents(context).application
  }
}

class AppComponents(context : play.api.ApplicationLoader.Context) extends BuiltInComponentsFromContext(context) with EhCacheComponents {
  lazy val assets = new controllers.Assets(httpErrorHandler)
  lazy val router: Router = new Routes(httpErrorHandler, assets, new controllers.TestController())
}

-

代码语言:javascript
复制
package controllers

class TestController extends Controller {
    def test = Action {
        Cache.getAs[String]("hello") map { result => 
            Ok(result)
        } getOrElse {
            Ok("not found")
        }
    }
}

配置:

代码语言:javascript
复制
# key, langs, etc. removed
play.application.loader = "AppApplicationLoader"
play.modules.enabled += "play.api.cache.EhCacheModule"

我怎么才能把这事做好?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2015-11-11 11:23:49

可以通过替换默认的注入器并添加更多的组件来做到这一点。我想这不再是编译时DI (因为依赖关系现在正在运行时被解析),但是它可以工作。

扩展BuiltInComponents

代码语言:javascript
复制
trait AppComponents(context: Context) extends BuiltInComponents 
  with I18nComponents 
  with EhCacheComponents {

    // other dependencies (e.g. router, assets) here

    //need to add any other components here that you want to reference via the global APIs  - 
    //e.g. csrfConfig from CSRFComponents      
    override lazy val injector: Injector = new SimpleInjector(
      NewInstanceInjector
    ) + router + crypto + httpConfiguration + defaultCacheApi  + messagesApi
}

不幸的是,您不能引用super.injector,因为它是一个lazy val,因此您不得不重新定义BuiltInComponents中已经存在的内容,这并不好。在将来升级播放时,检查添加到基本定义中的任何新组件是否被复制到新的实现中是很重要的。

在我的实际应用程序中,我使用的是MacWire,因此我编写了一个自定义注入器:

代码语言:javascript
复制
class MacwireInjector(fallback: Injector, wired: Wired) extends Injector {

  /**
    * Get an instance of the given class from the injector.
    */
  def instanceOf[T](implicit ct: ClassTag[T]) = instanceOf(ct.runtimeClass.asInstanceOf[Class[T]])

  /**
    * Get an instance of the given class from the injector.
    */
   def instanceOf[T](clazz: Class[T]) = wired.lookup(clazz) match {
    case instance :: Nil => instance
    case Nil => fallback.instanceOf(clazz)
    case set => throw new RuntimeException(s"Multiple instances returned for $clazz: $set")
  }

  /**
    * Get an instance bound to the given binding key.
    */
  def instanceOf[T](key: BindingKey[T]) = instanceOf(key.clazz)
}

BuiltInComponents:

代码语言:javascript
复制
// probably need to do this otherwise MacWire finds two candidates from EhCacheComponents
lazy val cacheApi = defaultCacheApi

override lazy val injector: Injector = new MacwireInjector(NewInstanceInjector, wiredInModule(this))

或者使用带有MacWire的默认注入器作为后盾:

代码语言:javascript
复制
override lazy val injector: Injector = new SimpleInjector(
  new MacwireInjector(NewInstanceInjector, wiredInModule(this))
) + router + crypto + httpConfiguration
票数 2
EN

Stack Overflow用户

发布于 2015-11-10 16:59:34

如果使用编译时依赖项注入,则应该通过对象的参数传递依赖关系:

代码语言:javascript
复制
class TestController(cache: CacheApi) extends Controller {
  ...
}

并在应用程序加载程序中传递实现:

代码语言:javascript
复制
class AppComponents(context : play.api.ApplicationLoader.Context) extends BuiltInComponentsFromContext(context) with EhCacheComponents {
  lazy val assets = new controllers.Assets(httpErrorHandler)
  lazy val controller = new controllers.TestController(defaultCacheApi)
  lazy val router: Router = new Routes(httpErrorHandler, assets, controller)
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33630385

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档