我在我的项目中使用lombok,其中有很多类@RequiredArgsConstructors
。我希望这些构造函数能够自动用于guice。
一个有用的选项是使用@RequiredArgsConstructors(onConstructor=@__(@Inject))
,但这既丑陋又实验性(读:未来可能会从lombok中消失)。
我想做的是制作自定义注入注释,比如说@InjectOnlyConstructor
来放置我的类定义并使用guice's SPI来绑定这些类型。但我无法弄清楚如何在SPI中发现这些类型。
如何查看guice的元素并绑定到这些构造函数,默认情况下guice会拒绝?
我希望课程看起来像的例子:
@Singleton
@InjectOnlyConstructor
@RequiredArgsConstructor
public class CatPictureService {
private final WebServiceClient client;
// Cool stuff that would make facebook cry
}
作为备份计划,我可以拥有一个模块来扫描我的项目包并自动绑定这些类型。
答案 0 :(得分:2)
我开始认为不可能挂钩Guice来解决未绑定的类型。
所以我提出了四种不同的解决方案。第一个是我最喜欢的,它包含官方Guice扩展使用的看似显式连接模式。您可以按如下方式使用它:
public class Bar {
private Bar(XYZ xyz) { ... }
}
Injector inject = Guice.createInjector(new AbstractModule() {
protected void configure() {
install(new OnlyConstructorBuilder(Bar.class));
}
});
OnlyConstructorBuilder
定义如下:
@RequiredArgsConstructor
private static class OnlyConstructorBuilder extends AbstractModule {
private final Class<?> type;
@Override
protected void configure() {
bindToOnlyConstructor(type);
}
@SuppressWarnings("unchecked")
private <T> void bindToOnlyConstructor(Class<T> type) {
Constructor<T>[] ctors = (Constructor<T>[])type.getDeclaredConstructors();
if (ctors.length > 1) {
addError("%s has too many constructors %s", type.getName(), Arrays.toString(ctors));
return;
} else if (ctors.length < 1) {
addError("%s needs at least one constructor", type.getName());
return;
} else {
bind(type).toConstructor(ctors[0]);
}
}
}
第二种方法是扫描类路径或其中的部分 - 寻找特定的注释。这是我最初的想法,如果你正在使用番石榴的反射助手,那就太难了。我以前做过类似的事,但人们发现它太神奇了。绑定部分与上面类似。
第三种方法是在模块中bind(Bar.class)
,并使用Elements SPI来寻找具有特定注释的UntargetedBinding
。但是因为我已经绑定了类,所以我也可以绑定到唯一的构造函数。
第四种方法是最糟糕的。它使用Elements API并确定每个绑定的依赖关系;使用特定注释搜索未绑定的依赖项。这是一条我不想走的路。