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.