How to delegate creation of some classes from Guic

2019-04-20 15:13发布

问题:

For instance, RESTEasy's ResteasyWebTarget class has a method proxy(Class<T> clazz), just like Injector's getInstance(Class<T> clazz). Is there a way to tell Guice that creation of some classes should be delegated to some instance?

My goal is the following behavior of Guice: when the injector is asked for a new instance of class A, try to instantiate it; if instantiation is impossible, ask another object (e. g. ResteasyWebTarget instance) to instantiate the class.

I'd like to write a module like this:

@Override
protected void configure() {
    String apiUrl = "https://api.example.com";
    Client client = new ResteasyClientBuilder().build();
    target = (ResteasyWebTarget) client.target(apiUrl);

    onFailureToInstantiateClass(Matchers.annotatedWith(@Path.class)).delegateTo(target);
}

instead of

@Override
protected void configure() {
    String apiUrl = "https://api.example.com";
    Client client = new ResteasyClientBuilder().build();
    target = (ResteasyWebTarget) client.target(apiUrl);

    bind(Service1.class).toProvider(() -> target.proxy(Service1.class);
    bind(Service2.class).toProvider(() -> target.proxy(Service2.class);
    bind(Service3.class).toProvider(() -> target.proxy(Service3.class);
}

I've thought about implementing Injector interface and use that implementation as a child injector, but the interface has too much methods.

I can write a method enumerating all annotated interfaces in some package and telling Guice to use provider for them, but that's the backup approach.

回答1:

Guice does not support this, it has no hooks for you to listen too. The hooks it does provide (ProvisionListener & TypeListener) don't get called if a binding can not be found.

I can write a method enumerating all annotated interfaces in some package and telling Guice to use provider for them, but that's the backup approach.

That is your only option. The optional injections only work if you are willing to spread your target.proxy love all over the codebase.

EDIT (2017-02-28): If you are going to do this, I've already done the basics to make it happen as part of my magic-provider-guice project, with examples for JDBI and Feign.

implementing Injector interface and use that implementation as a child injector

I don't believe you can set a child injector (just have Guice create one with a set of modules), so this would not work either.



回答2:

https://github.com/google/guice/wiki/Injections Check out Optional Injections, you can create a fall back with that.