I have successfully created a Guice binding annotation to inject single threaded java.util.concurrent.ExecutorService instances into a constructor.
here is an example usage:
public class ContainsSingleThreadedExecutorService {
private final ExecutorService executorService;
@Inject
public ContainsSingleThreadedExecutorService(@SingleThreaded ExecutorService executorService) {
this.executorService = executorService;
}
}
I now want to create a similar annotation for multi-threaded executors, specifying the ThreadPool size in the annotation. For example:
public class ContainsMultiThreadedExecutorService {
private final ExecutorService executorService;
@Inject
public ContainsMultiThreadedExecutorService(@MultiThreaded(poolSize = 5) ExecutorService executorService) {
this.executorService = executorService;
}
}
Does anyone out there know how I can access the value of the "poolSize" parameter from a Guice Provider?
You can't. That's not how binding annotations are intended to be used... the parameter would only serve to differentiate an ExecutorService
bound with @MultiThreaded(poolSize = 5)
from one bound with @MultiThreaded(poolSize = 2)
. It's not metadata to help configure a Provider
.
If you inject something annotated with @MultiThreaded(poolSize = 5)
, you need to have bound something with the annotation @MultiThreaded(poolSize = 5)
. If you then want to change the pool size you're using in all those places, you need to change poolSize = 5
to poolSize = 4
in both the place(s) where you bind it and in all the places you inject it. This doesn't make much sense to me.
Instead of binding ExecutorService
s by how many threads they have in their thread pool, you should bind them according to what you want to use them for. Then you can adjust the numbers of threads each one uses in one place.
Look at NamedImpl
that implements @Named
and method Names.named()
. I think you should have same implementation.
UPDATED
Guice
compares annotations by hashCode(). So, if you wont use @MultiThreaded(poolSize = 5)
you should map it before instancing. It seems like dirty workaround, but you can write smt like
for (int i = 1; i < 20; i++){
bind(ExecutorService.class).annotatedWith(Qualifiers.withValue(i)).toProvider(new DependencyProvider(i));
}
If you would like to do this. Remember, that your MultiThreadedImpl
should override hashCode
in proper way. It could be smt like
@Override
public int hashCode() {
return (127 * "poolSize".hashCode()) ^ value;
}
You can do this sort of thing (I once did almost exactly this) with Guice, but Guice really needs to know up-front what it's binding. So you would need to do something like:
for (int i=1; i < 100; i++) {
ExecutorService svc = Executors.newFixedThreadPool(i);
bind (ExecutorService.class).annotatedWith(new MultiThreadedImpl(i)).toInstance(svc);
}
(or more likely, bind to a Provider that lazily initializes it).
This is ugly enough that you probably don't actually want to do it. It's more useful to just use @Named and have a handful of ExecutorService instances which are tied to a name for the specific thing they are good for, anyway - then you can configure how many threads are used in one place, rather than having to wonder "is anybody using a 73-thread ExecutorService?"
Yes, you can. without iterator all situations.
Actually, I have the almost the same problem like your's. Here is my answer and question, with all my code. I only know how to do with field not parameter, but I think this is not a big problem, right ?
Follow CustomInjections in wiki you will know how.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With