AFAIK Provides annotation can only be used in Modules, thus is not a
preferable choice for me.

Base class approach is actually introducing another class, I just want to
reduce the provider class definitions.

I created custom injector, but this time I feel like I am doing guice's own
work, somewhat obnoxiously:

class SomeExecutorDependentClass{
    @InjectExecutor("pool")
    void setExecutor(ScheduledExecutorService e) {
        this.executor = e;
    }
}

class MyExecutors{
    public ExecutorService getExecutor(String name) {
        if (name.equals("pool")) {
            return pool;
        } else if (name.equals("sync")) {
            return synch;
        } else {
            throw new IllegalArgumentException("Executor name not found " +
name);
        }
    }
}

    public @interface InjectExecutor {
        String value();
    }

    public static TypeListener getInjectionListener(Provider<MyExecutors>
provider) {
        return new ExecutorTypeListener(provider);
    }

    static class ExecutorTypeListener implements TypeListener {

        private Provider<MyExecutors> provider;

        public ExecutorTypeListener(Provider<MyExecutors> provider) {
            this.provider = provider;
        }

        public <I> void hear(TypeLiteral<I> typeLiteral, TypeEncounter<I>
typeEncounter) {
            for (Method m : typeLiteral.getRawType().getDeclaredMethods()) {
                if (m.isAnnotationPresent(InjectExecutor.class)) {
                    typeEncounter.register(new ExecutorInjector<I>(m,
provider));
                }
            }
        }

    }

    static class ExecutorInjector<T> implements MembersInjector<T> {

        private Method method;

        private Provider<MyExecutors> provider;

        public ExecutorInjector(Method m, Provider<MyExecutors> provider) {
            this.method = m;
            this.provider = provider;
        }

        public void injectMembers(T instance) {
            boolean accessible = method.isAccessible();
            try {
                method.setAccessible(true);
                method.invoke(instance,

provider.get().getExecutor(method.getAnnotation(InjectExecutor.class).value()));
            } catch (Exception e) {
                throw new RuntimeException(e);
            } finally {
                method.setAccessible(accessible);
            }
        }
    }


On Wed, Mar 9, 2011 at 6:06 PM, Russ Milliken <[email protected]>wrote:

> I got the bindings wrong, correcting that.  Also illustrating how the
> superclass of Providers gets common dependencies.
>
>
> public class MyModule extends AbstractModule {
>
>     @Override
>     protected void configure() {
>         bind(ExecutorService.class)
>             .annotatedWith(Names.named("single"))
>             .toProvider(SingleProvider.class);
>
>         bind(ExecutorService.class)
>             .annotatedWith(Names.named("pool"))
>             .toProvider(PoolProvider.class);
>     }
> }
>
> class SomeDependency {}
> class AnotherDependency {}
> class CommonDependency1 {}
> class CommonDependency2 {}
> class CommonDependency3 {}
>
>
> abstract class GenericExecutorProvider implements Provider<ExecutorService>
> {
>
>     @Inject
>     GenericExecutorProvider(final CommonDependency1 d1,
>                             final CommonDependency2 d2,
>                             final CommonDependency3 d3) {}
>
>
>     public abstract ExecutorService get();
> }
>
> class SingleProvider extends GenericExecutorProvider {
>
>     @Inject
>     SingleProvider(final SomeDependency d,
>                    final CommonDependency1 d1,
>                    final CommonDependency2 d2,
>                    final CommonDependency3 d3) {
>         super(d1,d2,d3);
>
>     }
>
>     public ExecutorService get() {
>         // construct and return an ExecutorService
>         // based on SomeDependency
>         return null;
>     }
> }
>
> class PoolProvider extends GenericExecutorProvider {
>
>     @Inject
>     PoolProvider(final AnotherDependency d,
>                  final CommonDependency1 d1,
>                  final CommonDependency2 d2,
>                  final CommonDependency3 d3) {
>         super(d1,d2,d3);
>
>     }
>
>     public ExecutorService get() {
>         // construct and return an ExecutorService
>         // based on AnotherDependency
>         return null;
>     }
> }
>
>
> On Wed, Mar 9, 2011 at 10:18 AM, Russ Milliken <[email protected]>wrote:
>
>> I would do the "class" solution in a more OO way (eliminate the "switch"):
>>
>> public class MyModule extends AbstractModule {
>>
>>     @Override
>>     protected void configure() {
>>         bind(GenericExecutorProvider.class)
>>             .annotatedWith(Names.named("single"))
>>             .to(SingleProvider.class);
>>
>>         bind(GenericExecutorProvider.class)
>>             .annotatedWith(Names.named("pool"))
>>             .to(PoolProvider.class);
>>     }
>> }
>>
>> abstract class GenericExecutorProvider implements
>> Provider<ExecutorService> {
>>     public abstract ExecutorService get();
>> }
>>
>> class SingleProvider extends GenericExecutorProvider {
>>
>>     @Inject
>>     SingleProvider(final SomeDependency d) { }
>>
>>     public ExecutorService get() {
>>         // construct and return an ExecutorService
>>         // based on SomeDependency
>>         return null;
>>     }
>> }
>>
>> class PoolProvider extends GenericExecutorProvider {
>>
>>     @Inject
>>     PoolProvider(final AnotherDependency d) { }
>>
>>     public ExecutorService get() {
>>         // construct and return an ExecutorService
>>         // based on AnotherDependency
>>         return null;
>>     }
>> }
>>
>>
>> 2011/3/9 Sam Berlin <[email protected]>
>>
>> You can have one provider for both bindings, but the provider can't
>>> disambiguate based on what it's providing (that is, there's know of knowing
>>> the thing it's providing for).
>>>
>>> You could do this with less code with @Provides methods (or also simulate
>>> it if you're stuck with classes).  For example:
>>>
>>> @Provides @Named("single") ExecutorService
>>> provideSingle(AnotherDependency ad) {
>>>    return makeExecutor(ad, Type.SINGLE);
>>>  }
>>>
>>> @Provides @Named("pool") ExecutorService  providePool(AnotherDependency
>>> ad) {
>>>    return makeExecutor(ad, Type.POOL);
>>> }
>>>
>>> private ExecutorService  makeExecutor(AnotherDependency ad, Type type)
>>> {   ...  }
>>>
>>> ---  or, using classes ---
>>>
>>> class SingleProvider extends GenericExecutorProvider {
>>>   SingleProvider() {    super(Type.SINGLE);    }
>>>  }
>>>
>>> class PoolProvider extends GenericExecutorProvider {
>>>   PoolProvider() {   super(Type.POOL);  }
>>>  }
>>>
>>> class GenericExecutorProvider implmenets Provider<ExecutorService> {
>>>    final Type type;
>>>    GenericExecutorProvider(Type type) { this.type = type; }
>>>
>>>    @Inject injectDependency(AnotherDependency ad) { .... }
>>>
>>>    ExecutorService get() {
>>>       switch(type) { ... }
>>>    }
>>>  }
>>>
>>>
>>> sam
>>>
>>> 2011/3/9 Bahri Gençsoy <[email protected]>
>>>
>>>
>>>> Hi, I am trying to achieve some binding with Guice 2.0. I did search the
>>>> mailing list but couldn't find a similar problem/solution.
>>>>
>>>> I am trying to bind different implementations of same interface. I want
>>>> to discriminate them against their annotations.
>>>>
>>>> These are my classes to be injected dependencies to, I do not want to
>>>> change them a lot:
>>>>
>>>> class SingleRunner {
>>>>     @Inject
>>>>     public void setExecutor(@Named("single") ExecutorService executor) {
>>>>         // ...
>>>>     }
>>>> }
>>>>
>>>> class PoolRunner {
>>>>     @Inject
>>>>     public void setExecutor(@Named("pool") ExecutorService executor) {
>>>>         // ...
>>>>     }
>>>> }
>>>>
>>>> This is the traditional approach to bind providers for these classes;
>>>> creating to provider classes and bind them:
>>>>
>>>> class SingleProvider implements Provider<ExecutorService> {
>>>>     @Inject
>>>>     private SomeOtherDependency other;
>>>>
>>>>     public ExecutorService get() {
>>>>         return singleExecutorService;
>>>>     }
>>>>
>>>> }
>>>>
>>>> class PoolProvider implements Provider<ExecutorService> {
>>>>     @Inject
>>>>     private SomeOtherDependency other;
>>>>
>>>>     public ExecutorService get() {
>>>>         return poolExecutorService;
>>>>     }
>>>>
>>>> }
>>>>
>>>> class MyModule extends AbstractModule {
>>>>     @Override
>>>>     protected void configure() {
>>>>
>>>> bind(ExecutorService.class).annotatedWith(Names.named("pool")).toProvider(PoolProvider.class);
>>>>
>>>> bind(ExecutorService.class).annotatedWith(Names.named("single")).toProvider(SingleProvider.class);
>>>>     }
>>>> }
>>>>
>>>> But I am not comfortable with creating two provider classes. I want one
>>>> provider class to provide all instances, ie something like that:
>>>>
>>>> class AllExecutorProvider {
>>>>     @Inject
>>>>     public void setSomeOtherDependency(SomeOtherdependency dep) {
>>>>         // ...
>>>>     }
>>>>
>>>>     public ExecutorService getExecutor(String name) {
>>>>         if (name.equals("pool")) {
>>>>             return poolExecutor;
>>>>         } else if (name.equals("single")) {
>>>>             return singleExecutor;
>>>>         } else {
>>>>             return null;
>>>>         }
>>>>     }
>>>> }
>>>>
>>>>
>>>> Thanks in advance
>>>>
>>>>
>>>>  --
>>>> You received this message because you are subscribed to the Google
>>>> Groups "google-guice" group.
>>>> To post to this group, send email to [email protected].
>>>> To unsubscribe from this group, send email to
>>>> [email protected].
>>>> For more options, visit this group at
>>>> http://groups.google.com/group/google-guice?hl=en.
>>>>
>>>
>>>  --
>>> You received this message because you are subscribed to the Google Groups
>>> "google-guice" group.
>>> To post to this group, send email to [email protected].
>>> To unsubscribe from this group, send email to
>>> [email protected].
>>> For more options, visit this group at
>>> http://groups.google.com/group/google-guice?hl=en.
>>>
>>
>>
>

-- 
You received this message because you are subscribed to the Google Groups 
"google-guice" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/google-guice?hl=en.

Reply via email to