[英]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.
现在我脑子里有两个问题。
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 建模。
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 的这个问题,请检查以下解决方法
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 BrainTree
和class 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.