Java Guice多注释
我有一个名为Java Guice多注释,java,guice,Java,Guice,我有一个名为StatsStore的接口。我有这个商店的两个实现。一个名为InMemoryStatsStore和SqlStatsStore的内存和SQL实现。为了注入它们,我创建了两个注释@InMemoryStore和@SqlStore。注射方法如下: bind(StatsStore.class) .annotatedWith(InMemoryStore.class) .to(InMemoryStatsStore.class); bind(StatsStore.class)
StatsStore
的接口。我有这个商店的两个实现。一个名为InMemoryStatsStore
和SqlStatsStore
的内存和SQL实现。为了注入它们,我创建了两个注释@InMemoryStore
和@SqlStore
。注射方法如下:
bind(StatsStore.class)
.annotatedWith(InMemoryStore.class)
.to(InMemoryStatsStore.class);
bind(StatsStore.class)
.annotatedWith(SqlStore.class)
.to(SqlStatsStore.class);
现在我想添加一个新的注释层,以在InMemoryStringStore
和InMemoryNumberStore
之间进行分隔,但我不能向绑定行添加多个注释,例如,以下内容无法编译:
bind(StatsStore.class)
.annotatedWith(InMemoryStore.class)
.annotatedWith(NumberStoreAnnotation.class) // using named doesn't work as well
.to(InMemoryNumberStore.class);
我怎样才能添加多个注释而不使用一个命名的注释呢?添加的图层越多,注释就越复杂
我想到的另一个解决方案是注射两次:
bind(StatsStore.class)
.annotatedWith(InMemoryStore.class)
.to(InMemoryStatsStore.class);
bind(InMemoryStatsStore.class)
.annotatedWith(NumberStoreAnnotation.class)
.to(InMemoryNumberStore.class);
谢谢大家 你:
@BindingAnnotation
告诉Guice这是一个绑定注释Guice将产生一个错误,如果有多个绑定注释应用于同一个成员
你可以使用命名绑定,或者你应该考虑重新设计你的解决方案。
正如Amit所说,你不能有一个以上的bdin注释适用于任何给定的注入。在内部,Guice的工作方式类似于
映射
,其中键可能是一个参数化类,带有可选的单个注释实例。但是,因为这些都是实例,所以欢迎您使用命名的工作方式
@Inject @InMemoryStore(NUMBER) StatsStore inMemoryNumberStore;
@Inject @SqlStore(STRING) StatsStore sqlStringStore;
// or
@Inject @Store(dataType=NUMBER, backend=SQL) sqlNumberStore;
注释必须具有这样定义的字段。(如果有一个元素名为value
,则可以省略属性名。)定义了相等的注释
这对于@提供了,当您可以以注入注释的相同方式调用注释时,效果很好,但是如何为name.named等实例创建工厂方法呢?为此,您需要执行以下操作之一:
,具有每个属性的访问器以及equals
和hashCode
的正确实现。请注意,hashCode
契约是,但您可以从或类似的库中获得兼容的实现
使用,它为任意子类提供equals
和hashCode
实现
使用或类似的代码生成器为您的兼容实现生成代码。熟悉这种类型的解决方案对于Android和其他反射速度较慢的内存受限环境特别有用,尽管这样的环境通常会阻止您使用Guice。(@Qualifier
注释在其他与JSR-330兼容的依赖项注入框架(包括Dagger)中的工作方式相同。)
如果以上内容看起来有点复杂,或者如果您想要比Guice基于映射的实现更复杂的逻辑,一种替代方法是添加一层您可以控制的间接寻址:
public class StoreStore {
@Inject Provider<InMemoryNumberStore> inMemoryNumberStoreProvider;
// ...
// You can also inject the Injector to call getInstance with a class literal.
public StatsStore getStore(DataType dataType, Backend backend) {
// This can also be a switch or any other sort of lookup, of course.
if (dataType == NUMBER && backend == IN_MEMORY) {
return inMemoryNumberStoreProvider.get();
} // ...
}
}
公共类存储{
@在MemoryNumberStoreProvider中插入提供程序;
// ...
//您还可以注入注入器以使用类文本调用getInstance。
公共StatsStore getStore(数据类型DataType,后端){
//当然,这也可以是一个开关或任何其他类型的查找。
if(数据类型==数字和后端==内存中){
返回inMemoryNumberStoreProvider.get();
} // ...
}
}
我可以添加多个名称而不仅仅是一个长名称吗?如果可能的话,我想避免在内存中使用类似于states.\u tore.\u memory.number
…的名称。感谢您的深入解释和解决方案。实际实现注释的一个很好的替代方法就是使用@Provides
方法。@Tavian:是的!如上所述(“效果很好…”)。
public class StoreStore {
@Inject Provider<InMemoryNumberStore> inMemoryNumberStoreProvider;
// ...
// You can also inject the Injector to call getInstance with a class literal.
public StatsStore getStore(DataType dataType, Backend backend) {
// This can also be a switch or any other sort of lookup, of course.
if (dataType == NUMBER && backend == IN_MEMORY) {
return inMemoryNumberStoreProvider.get();
} // ...
}
}