Guice中的绑定:编译时间依赖性

时间:2015-10-28 21:32:48

标签: java dependency-injection guice

在探索Guice时,我对注入依赖项的方式提出了疑问。

根据我的理解,DI的一个重要方面是,依赖性是已知的并且是在运行时注入的。

在Guice中,要注入依赖项,我们需要添加绑定或实现提供程序。添加依赖项需要一个类对象,该类对象在该类上添加编译时依赖项。避免这种情况的一种方法是将其实现为提供程序,并让提供程序使用反射来动态加载类。

public class BillingModule extends AbstractModule {

@Override
protected void configure() {
    bind(CreditCardProcessor.class).toProvider(
            BofACreditCardProcessorProvider.class);
    bind(CreditCardProcessor.class).annotatedWith(BofA.class).toProvider(
            BofACreditCardProcessorProvider.class);
    bind(CreditCardProcessor.class).annotatedWith(Amex.class).toProvider(
            AmexCreditCardProcessorProvider.class);
}

@Provides
PaymentProcessor createPaymentProcessor() {
    return new PayPalPaymentProcessor();
}

@Provides
PayPalPaymentProcessor createPayPalPaymentProcessor() {
    return new PayPalPaymentProcessor();
}}

为什么Guice选择类对象而不是类名?那可能已经删除了编译时依赖性吗?

1 个答案:

答案 0 :(得分:2)

如果您的接口实现在同一个依赖项中定义(即在同一个JAR文件中),那么您已经对实现具有硬构建依赖性,你是否使用Guice。

基本上,只要你有:

public final class MyClass {
  public void doSomething(Foo foo);
}

然后编译MyClass Foo的定义需要在编译时类路径上。

解决此问题的方法是将接口与实现分开。例如,如果Foo是一个接口,并且FooImpl是它的实现,那么您可以将FooImpl放在{{1}的不同依赖项(即不同的JAR文件)中}}

现在,让我们假设您在Maven中有两个子项目:

Foo

绑定foo-api/ pom.xml src/main/java/com/foo/Foo.java foo-impl/ pom.xml src/main/java/com/foo/FooImpl.java 的Guice模块应该在哪里生效?它不应该存在于Foo项目中,它应该与foo-api一起存在于foo-impl项目中。

现在假设您有FooImpl的单独实现(让我们称之为Foo),您的项目需要SuperFoo,但它可能是{{1} }或Foo

如果我们将FooImpl作为自己的项目:

SuperFoo

现在您的所有应用程序代码都可以SuperFoo并使用foo。在super-foo/ pom.xml src/main/java/com/super/foo/SuperFoo.java src/main/java/com/super/foo/SuperFooModule.java 方法中(或在您创建@Inject Foo的任何位置),您需要决定是安装main()(来自Injector)还是FooModule(来自{{ 1}})。

那个是可以保证反思的地方。例如,您可以将配置标记foo-impl设置为SuperFooModulesuper-foo。您可以使用以下代码决定安装哪一个:

foo_module

当然,您也可以使用任何其他机制来选择要安装的模块。在许多情况下,您甚至不想反思地执行此操作,只需在更改构建依赖项的同时更改代码即可。