custom Guice binding annotations with parameters

前端 未结 4 514
被撕碎了的回忆
被撕碎了的回忆 2020-12-11 03:41

I have successfully created a Guice binding annotation to inject single threaded java.util.concurrent.ExecutorService instances into a constructor.

here is an exampl

相关标签:
4条回答
  • 2020-12-11 04:22

    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 ExecutorServices 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.

    0 讨论(0)
  • 2020-12-11 04:22

    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;
    }
    
    0 讨论(0)
  • 2020-12-11 04:22

    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?"

    0 讨论(0)
  • 2020-12-11 04:24

    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.

    0 讨论(0)
提交回复
热议问题