【问题标题】:Injection via Guice into an Immutables class通过 Guice 注入 Immutables 类
【发布时间】:2018-01-01 10:41:48
【问题描述】:

我正在使用 2 个常用包,ImmutablesGuice。在运行时发生的第一件事是我将环境和其他来源的设置加载到一个单例、非不可变的配置类中,我们称之为MyConfig,例如,公开一个公共getSettingX() 方法。

 MyConfig myConfig = MyConfig.intialize().create();  
 String settingX = myConfig.getSettingX();

我有一个抽象的不可变类,叫它AbstractImmutable。在实例化时需要根据myConfig.getSettingX() 设置一个字段。

@Value.Immutable
abstract class AbstractImmutable {
   abstract String getSettingX(); // Ideally set 
}

现在,通常我使用 Guice 将 MyConfig 注入到类中,并且想找到一种方法来实现 AbstractImmutable 类(以避免每次构建时都必须手动注入 MyConfig 类一个对象——整个原因是使用果汁来管理我的 DI)。但是,由于具体的 Immutables 类是在编译时生成的,因此它不适用于通常的 Guice 注入注解。

Immutables 网站上有使用 builder 包注释静态工厂方法的指示,但我似乎不知道如何将其添加到抽象不可变类中。

大家有什么建议吗?

【问题讨论】:

  • 对我来说听起来像是一个糟糕的设计,你需要它做什么?您是否出于某些原因需要配置快照?
  • 通过注入依赖来初始化不可变对象是一个糟糕的设计吗?
  • 不是这样,但是抽象类AbstractImmutable对我来说毫无意义,谁以及出于什么原因来扩展它,这个类是干什么用的?这让我很困惑这段代码应该做什么,它的用途是什么?我不知道......因此这是糟糕的设计。
  • 这只是示例的名称,如果您愿意,可以将其命名为AbstractCarrot。 Immutables 库将在编译时基于AbstractCarrot 类创建一个concreate Carrot 类,只要它被注释为@Immutable。您不扩展它,Immutables 会,检查问题中的链接以了解 Immutables 库的工作原理。例如,如果您是 Bunny 类,您将使用 Carrot
  • 我知道,但这对我来说仍然没有意义......至于你的问题,只需在 AbstractImmutable 中创建一个构造函数,它需要 MyConfig 并用 @Inject 标记这个构造函数

标签: java dependency-injection guice immutability immutables-library


【解决方案1】:

据我所知,没有办法在生成的 Immutables 类本身上执行此操作(尽管您可以使用 @InjectAnnotation 做一些有趣的事情),因此您可能不走运。

即使您是打着 Guice 的幌子提出问题,但您提出的问题让我想起了 AutoFactory 使用的模式,并且应该同样适用。本质上,通过注入工厂来利用Factory Pattern,然后工厂将创建不可变对象。

例如,特指你的情况,

@Value.Immutable
abstract class ValueObject {
    MyConfig getMyConfig();

    @Value.Derived
    String getSettingX() {
        getMyConfig().getSettingX();
    }

    String getAnotherProperty();

    class ValueObjectFactory {
        @Inject MyConfig myConfig;

        ValueObject create(String anotherProperty) {
            return ImmutableValueObject.builder()
                .setMyConfig(this.myConfig)
                .setAnotherProperty(anotherProperty)
                .build();
        }
    }
}

然后,在应用程序代码中,您将直接注入 ValueObjectFactory 并在其上调用 create

class SomeApplicationClass {
    @Inject ValueObjectFactory factory;

    void someMethod() {
        ValueObject = factory.create("myString");

        // ... do something with the ValueObject
    }
}

同样,您可以将您的工厂定义为建造者,但这将是您必须根据您拥有的参数数量做出的决定。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-11-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多