Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Guice inject different instance based on the parent instance annotation

I am using guice framework in my application. I have a scenario where a single class might require multiple instances of same interface C (but for different purposes) as shown in the example. I am trying to resolve this using the annotation facility in guice.

As shown in the example below, I want the config for ConcreteImpl also to be injected by guice. But the problem is the config for type1, type2 and type3 instances could be different. Assuming that I have the configurations for these instances apriori, is there a facility to inject them according to the context (denoted by annotation) of instance requesting the config?

    class A {
        @Inject
        public A(@Purpose1 C type1, @Purpose2 C type2, @Purpose3 C type3) {

        }
    }

    interface C {}

    class ConcreteImpl implements C {
        @Inject
        public ConcreteImpl(ConcreteImplConfig config) {}
    }

    class ConcreteImplConfig {
        String pty1;
        String pty2;
    }  

My module binding is like this -

    bind(C.class)
            .annotatedWith(Purpose1.class)
            .to(purpose1Cklass/**obtained from config**/);

    bind(C.class)
            .annotatedWith(Purpose2.class)
            .to(purpose2Cklass/**obtained from config**/);

    bind(C.class)
            .annotatedWith(Purpose3.class)
            .to(purpose3Cklass/**obtained from config**/);

And this is pretty much what I want to do

    bind(ConcreteImplConfig.class)
            .requestedThrough(Purpose1.class)
            .toInstance(purpose1config);

    bind(ConcreteImplConfig.class)
            .requestedThrough(Purpose2.class)
            .toInstance(purpose2config);

    bind(ConcreteImplConfig.class)
            .requestedThrough(Purpose3.class)
            .toInstance(purpose3config);

I already had a look at assisted inject, which can inject a factory and then we use factory.create(config) but I am not inclined to that as the contracts tend to become slightly uglier and all the more i have all the configs at the start of my application and should be able to inject them.

like image 913
amrk7 Avatar asked Nov 30 '25 23:11

amrk7


1 Answers

This is the Robot Leg Problem. You need to create a private module for C.

abstract class CModule extends PrivateModule {
    private final Class<? extends Annotation> annotation;

    CModule(Class<? extends Annotation> annotation) {
        this.annotation = annotation;
    }

    @Override protected void configure() {
        bind(C.class).annotatedWith(annotation).to(C.class);
        expose(C.class).annotatedWith(annotation);

        bindConfig();
    }

    abstract void bindConfig();
}

public static void main(String[] args) {
        Injector injector = Guice.createInjector(
                new CModule(Propsal1.class) {
                    @Override void bindConfig() {
                        bind(ConcreteImplConfig.class).toInstance(new ConcreteImplConfig());
                    }
                },
                new CModule(Propsal2.class) {
                    @Override void bindConfig() {
                        bind(ConcreteImplConfig.class).toInstance(new ConcreteImplConfig());
                    }
                },
                new CModule(Propsal2.class) {
                    @Override void bindConfig() {
                        bind(ConcreteImplConfig.class).toInstance(new ConcreteImplConfig());
                    }
                }
                );
    }
like image 198
Michael Lloyd Lee mlk Avatar answered Dec 03 '25 12:12

Michael Lloyd Lee mlk



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!