简体   繁体   English

Scala - 伴随对象中的依赖注入

[英]Scala - Dependency injection in companion objects

I am from Java background and new to functional paradigm as such, so please forgive and correct me I smell like OOP.我来自 Java 背景并且不熟悉函数范式,所以请原谅并纠正我,我闻起来像 OOP。

I have a trait names PaymentHandler我有一个特征名称 PaymentHandler

trait PaymentHandler {

def handleInit(paymentInfo: PaymentInfo, paymentConfig: PaymentConfig): Either[Future[WSResponse], Exception]

def handleComplete(paymentinfo: PaymentInfo, paymentConfig: PaymentConfig, clientToken: String): Future[Map[String, String]]

}

and

@Singleton
class PayPal extends PaymentHandler{....}
@Singleton
class BrainTree extends PaymentHandler{....}

Till here everything is Ok.到这里一切正常。 but the problem comes when I want to have multiple PaymentGateways based on Payment method.但是当我想要基于 Payment 方法拥有多个 PaymentGateways 时,问题就来了。 Initially I wrote a PaymentHandlerFactory like最初我写了一个 PaymentHandlerFactory 像

class PaymentHandlerFactory @Inject()(
    paypal:PayPal,
    braintree:BrainTree) {

  def get(name:String): PaymentHandler = {
     name match {
       case "paypal" => paypal
       case "bt" => braintree
       case _ => null
     }
  }
}

and then use this PaymentHandlerFactory to get the PayPal object injected by guice.然后使用这个 PaymentHandlerFactory 来获取 guice 注入的 PayPal 对象。 But somehow I felt this is not right way to do and I got onto companion objects.但不知何故,我觉得这不是正确的做法,于是我找到了伴生对象。 so this is the code I wrote then所以这是我当时写的代码

object PaymentHandler {
  @Inject
  val paypal:PayPal = null

  def apply(name:String): PaymentHandler = {
    name match {
      case "paypal" => paypal
      case _ => null
    }
  }
}

Ofcourse this fails as it cannot Inject PayPal object.当然这失败了,因为它不能注入 PayPal 对象。 Now I have two questions in my mind.现在我脑子里有两个问题。

  1. Why we cannot inject in companion objects in scala?为什么我们不能在 Scala 中注入伴生对象?
  2. What is the right way to implement such factory like things in scala?在 Scala 中实现这样的工厂的正确方法是什么?
  1. The reason you cannot inject in companion object is because they are objects rather than classes.不能注入伴生对象的原因是因为它们是对象而不是类。 This means only a single instance exists and that is created by scala itself.这意味着只有一个实例存在并且由 Scala 本身创建。 If you want to do dependency injection, then the thing that requires the dependency must be created by the dependency injection framework.如果要做依赖注入,那么需要依赖的东西必须由依赖注入框架创建。 Therefore, you need to model your fatory using a class if you want to use guice.因此,如果你想使用 guice,你需要使用一个类来为你的 fatory 建模。

  2. I think what you did with your class PaymentHandlerFactory is the pragmatic way and probably works in most cases.我认为你对你的class PaymentHandlerFactory是务实的方式,可能在大多数情况下都有效。 I would refrain from prematurely making this too generic.我会避免过早地使这过于通用。

If you want to make it a bit more guice-y, you could use their AssistedInject .如果你想让它更漂亮一点,你可以使用他们的AssistedInject

If you land up on this question about DI on companion objects, please check the below workaround如果您遇到关于伴随对象上的 DI 的这个问题,请检查以下解决方法

  • using a corresponding class with DI使用带有 DI 的相应类
  • create a companion object on this class在这个类上创建一个伴生对象

The benefit of DI is that it will be propagated to this companion object. DI 的好处是它将传播到这个伴随对象。

If you have a companion object on class Paypal and class BrainTree as below:如果您在class Paypal class BrainTreeclass BrainTree上有一个伴生对象,如下所示:

@Singleton
class PayPal extends PaymentHandler{....}
object PayPal extends PayPal
@Singleton
class BrainTree extends PaymentHandler{....}
object BrainTree extends BrainTree

Now, I can use these objects in the PaymentHandler companion object as below:现在,我可以在 PaymentHandler 伴随对象中使用这些对象,如下所示:

// get the correct handler from factory
class PaymentHandler extends PaymentHandlerFactory(PayPal, BrainTree){...}
object PaymentHandler extends PaymentHandler

Now in any class, we can use PaymentHandler.get()现在在任何类中,我们都可以使用PaymentHandler.get()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM