英文:
Google Guice Named vs Annotation
问题
我正在阅读Google Guice的文档,并了解了UntargettedBinding。基本上有两个选项:
- @Named
- 绑定注释
我的问题是,哪个选项更好?
使用@Named
,我不必创建样板代码来使用annotations
,但代价是类型安全性较低。在我看来,注释代码看起来更清晰。
英文:
I was going through Google Guice documentation and read about UntargettedBinding. Basically there are two options
- @Named
- Binding annotation
My question is, which one is better?
With @Named
I dont have to create boiler plates to use annotations
but it comes at cost of less type safety. Annotation code looks more cleaner IMHO.
答案1
得分: 2
你在这里详细解释了绑定注释的优缺点。你的陈述是正确的。
@Named 的另一个优点是可以使用 Names.bindProperties 来绑定属性。
在使用绑定注释无关紧要的情况下,可以查看如何加载属性。
对于 UntargetBinding(听起来就像是实际的问题),文档中列出了两个选项。
如果你不想使用绑定注释/@Named,只需声明对具体类的绑定。例如:
bind(MyConcreteClass.class);
bind(AnotherConcreteClass.class).in(Singleton.class);
如果你需要使用绑定注释/@Named,你必须仍然添加目标绑定,即“.toSometing” 方法(to、toProvider、toContractor 等)。例如:
public class TestUntargetBinding {
@Test
void testTargetBindingViaImplementBy() {
final var injector = Guice.createInjector(new AbstractModule() {
@Override
public void configure() {
bind(MyConcreteClass.class)
.annotatedWith(Names.named("100"))
.toProvider(() -> new MyConcreteClass(100));
bind(MyConcreteClass.class)
.annotatedWith(Names.named("200"))
.toProvider(() -> new MyConcreteClass(200));
}
});
//假设有一个带构造函数的类
// @Inject
// SomeClass(@Named("100") MyConcreteClass myConcreteClass1){...}
final var myConcreteClass1 = injector.getInstance(Key.get(MyConcreteClass.class, Names.named("100")));
final var myConcreteClass2 = injector.getInstance(Key.get(MyConcreteClass.class, Names.named("200")));
assertThat(myConcreteClass1.doSomething(), Is.is(100));
assertThat(myConcreteClass2.doSomething(), Is.is(200));
}
static class MyConcreteClass {
private int i;
public MyConcreteClass(int i) {
this.i = i;
}
public int doSomething() {
return i;
}
}
}
除非你指定了“toProvider”,Guice 将不知道要将名称/注释绑定到哪个类。
英文:
You specified the Pros and Cons of binding annotation in general as explained here.<br>
Your statements are correct.
One more advantage of @Named is to bind for properties using Names.bindProperties.
Where using binding annotation is irrelevant.
See how to load properties
For UntargetBinding (which sound like it was the actual question) the documentation states two options
If you don't want to use binding annotation/@Named just declare the bind to the concrete class.<br>
E.g.
bind(MyConcreteClass.class);
bind(AnotherConcreteClass.class).in(Singleton.class);
You need to use binding annotation/@Named you must still add the target binding i.e. the ".toSometing" methods (to, toProvider, toContractor etc.)
For example:
public class TestUntargetBinding {
@Test
void testTargetBindingViaImplementBy() {
final var injector = Guice.createInjector(new AbstractModule() {
@Override
public void configure() {
bind(MyConcreteClass.class)
.annotatedWith(Names.named("100"))
.toProvider(() -> new MyConcreteClass(100));
bind(MyConcreteClass.class)
.annotatedWith(Names.named("200"))
.toProvider(() -> new MyConcreteClass(200));
}
});
//imagine a class with a constructor
// @Inject
// SomeClass(@Named("100) MyConcreteClass myConcreteClass1){...}
final var myConcreteClass1 = injector.getInstance(Key.get(MyConcreteClass.class, Names.named("100")));
final var myConcreteClass2 = injector.getInstance(Key.get(MyConcreteClass.class, Names.named("200")));
assertThat(myConcreteClass1.doSomething(), Is.is(100));
assertThat(myConcreteClass2.doSomething(), Is.is(200));
}
static class MyConcreteClass {
private int i;
public MyConcreteClass(int i) {
this.i = i;
}
public int doSomething() {
return i;
}
}
}
Guice will not know witch class to bind the name/annotation to unless you will specify the "toProvider"
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论