制作自定义@Inject 注释

Making a custom @Inject annotation

我在我的项目中使用 lombok,其中有很多 classes 与 @RequiredArgsConstructors。我希望在 guice 中自动使用这些构造函数。

一个可行的选择是使用 @RequiredArgsConstructors(onConstructor=@__(@Inject)) 但这既丑陋又实验性(阅读:将来可能会从 lombok 中消失)。

我想做的是做一个自定义注入注释,说 @InjectOnlyConstructor 放在我的 class 定义上,并使用 guice's SPIs 来绑定这些类型。但是我不知道如何在 SPI 中发现这些类型。

我如何查看 guice 的元素并绑定到 guice 默认拒绝的这些构造函数?

我希望 class 看起来像的示例:

@Singleton
@InjectOnlyConstructor
@RequiredArgsConstructor
public class CatPictureService {
    private final WebServiceClient client;

    // Cool stuff that would make facebook cry
}

作为备用计划,我可以有一个模块来扫描我项目的包并自动绑定这些类型。

我开始认为不可能挂接到 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]);
        }
    }
}

第二种方法是扫描 class 路径(或其中的一部分)以查找特定注释。这是我最初的想法,如果您使用 Guava 的反射助手,这并不难。我以前做过类似的事情,但人们觉得它太神奇了。绑定部分同上。

第三种方法是在模块中 bind(Bar.class) 并使用 Elements SPI 查找带有特定注释的 UntargetedBinding。但由于我已经绑定了 class,我还不如绑定到唯一的构造函数。

第四种方法是最糟糕的。它使用元素 API 并确定每个绑定的依赖关系;使用特定注释搜索未绑定的依赖项。这是一条我不想走下去的路