简体   繁体   中英

Injection via Guice into an Immutables class

I'm using 2 common packages, Immutables and Guice . The very first thing that happens at runtime is I load setting from environment and other sources into settings into a singleton, non-Immutable config class, let's call it MyConfig , that for example, exposes a public getSettingX() method.

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

I have one abstract Immutable class, call it AbstractImmutable . that at instantiation needs to set a field based on the myConfig.getSettingX() .

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

Now, typically I inject MyConfig into classes using Guice, and would liket to figure a way to do this for implementations of the AbstractImmutable class (to avoid manually having to inject the MyConfig class every time I build an object--whole reason using juice to begin with, to manage my DI). However, since the concrete Immutables classes are generated at compile, it doesn't to work with the usual Guice injection annotations.

There's indication on the Immutables site of using the builder package to annotate a static factory method, but I can't seem to figure how to add this to the abstract immutable class.

Anyone have any suggestions?

To my knowledge, there is no way to do this on the generated Immutables class itself (though there may be some funny stuff you could do with @InjectAnnotation ), so you may be out of luck there.

Even though you are asking under the guise of Guice, what you are asking for reminds me of the pattern that AutoFactory uses, and should be similarly applicable. In essence, take advantage of the Factory Pattern by injecting into the factory and then the factory will create the Immutable object.

For example, specifically referring to your case,

@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();
        }
    }
}

Then, in the application code, you would inject the ValueObjectFactory directly and call create on it as

class SomeApplicationClass {
    @Inject ValueObjectFactory factory;

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

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

Similarly, you could define your factory as a builder, but that will be a decision you will have to make based on the number of parameters you have.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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