简体   繁体   English

自定义Guice绑定注释与参数

[英]custom Guice binding annotations with parameters

I have successfully created a Guice binding annotation to inject single threaded java.util.concurrent.ExecutorService instances into a constructor. 我已经成功创建了一个Guice绑定注释,将单线程java.util.concurrent.ExecutorService实例注入到构造函数中。

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. 我现在想为多线程执行程序创建一个类似的注释,在注释中指定ThreadPool大小。 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? 有没有人知道如何从Guice提供程序访问“poolSize”参数的值?

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) . 这不是打算如何使用绑定注释...该参数仅用于区分与@MultiThreaded(poolSize = 5)绑定的ExecutorService@MultiThreaded(poolSize = 5)绑定的一个@MultiThreaded(poolSize = 2) It's not metadata to help configure a Provider . 帮助配置Provider不是元数据。

If you inject something annotated with @MultiThreaded(poolSize = 5) , you need to have bound something with the annotation @MultiThreaded(poolSize = 5) . 如果你注入了用@MultiThreaded(poolSize = 5)注释的@MultiThreaded(poolSize = 5) ,你需要用注释@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. 如果您想要更改在所有这些位置使用的池大小,则需要在绑定它的位置和注入它的所有位置将poolSize = 5更改为poolSize = 4 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. 不是通过它们在线程池中有多少线程来绑定ExecutorService ,而是应该根据你想要使用它们来绑定它们。 Then you can adjust the numbers of threads each one uses in one place. 然后,您可以调整每个人在一个地方使用的线程数。

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. 你可以用Guice做这种事情(我曾经几乎完成了这一点),但Guice真的需要事先了解它的约束力。 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?" 使用@Named并拥有一些ExecutorService实例更有用,这些实例与他们适合的特定事物的名称相关联 - 然后你可以配置在一个地方使用多少线程,而不是不得不怀疑“有人使用73线程的ExecutorService吗?”

Look at NamedImpl that implements @Named and method Names.named() . 看看NamedImpl实现@Named和方法Names.named() I think you should have same implementation. 我认为你应该有相同的实现。

UPDATED Guice compares annotations by hashCode(). UPDATED Guice通过hashCode()比较注释。 So, if you wont use @MultiThreaded(poolSize = 5) you should map it before instancing. 所以,如果你不使用@MultiThreaded(poolSize = 5)你应该在实例化之前映射它。 It seems like dirty workaround, but you can write smt like 这似乎是脏的解决方法,但你可以写像smt一样

    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. 请记住,您的MultiThreadedImpl应以适当的方式覆盖hashCode It could be smt like 它可能像smt一样

@Override
public int hashCode() {
    return  (127 * "poolSize".hashCode()) ^ value;
}

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. 在wiki中关注CustomInjections ,您将了解如何操作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM