制作自定义@Inject注释

时间:2015-10-01 18:42:59

标签: guice lombok

我在我的项目中使用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
}

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

1 个答案:

答案 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并确定每个绑定的依赖关系;使用特定注释搜索未绑定的依赖项。这是一条我不想走的路。