gpt4 book ai didi

java - Guice 中的绑定(bind) : Compile time dependencies

转载 作者:塔克拉玛干 更新时间:2023-11-02 08:41:06 29 4
gpt4 key购买 nike

在探索 Guice 时,我对注入(inject)依赖项的方式有疑问。

根据我的理解,DI 的重要方面之一是,依赖项是已知的并在运行时注入(inject)。

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

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 选择类对象而不是类名是有原因的吗?那可以消除编译时依赖吗?

最佳答案

如果你的interfaceimplementation 是在同一个依赖项中定义的(也就是说,在同一个JAR 文件中)那么你已经对实现有一个硬构建依赖项,无论您是否使用 Guice。

基本上,只要你有:

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

然后要编译 MyClassFoo 的定义需要在编译时类路径中。

解决这个问题的方法是将接口(interface)从实现中分离出来。例如,如果 Foo 是一个接口(interface),而 FooImpl 是它的实现,您可以将 FooImpl 放在不同的依赖项中(即,一个不同的 JAR 文件)来自 Foo

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

foo-api/
pom.xml
src/main/java/com/foo/Foo.java

foo-impl/
pom.xml
src/main/java/com/foo/FooImpl.java

绑定(bind) Foo 的 Guice 模块应该放在哪里?它不应该存在于 foo-api 项目中,它应该存在于 foo-impl 项目中,与 FooImpl 一起存在。

现在假设您有一个单独的 Foo 实现(我们称它为 SuperFoo),并且您的项目需要一个 Foo,但它可以可以是 FooImplSuperFoo

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

super-foo/
pom.xml
src/main/java/com/super/foo/SuperFoo.java
src/main/java/com/super/foo/SuperFooModule.java

现在您所有的应用程序代码都可以简单地 @Inject Foo 并使用 foo.在您的 main() 方法(或您创建 Injector 的任何位置)中,您需要决定是否安装 FooModule(来自 foo- impl) 或 SuperFooModule(来自 super-foo)。

是值得反射(reflection)的地方。例如,您可以有一个配置标志 foo_module,它可以设置为 "com.foo.FooModule""com.super.foo.SuperFooModule"。您可以使用如下代码决定安装哪一个:

public static void main(String[] args) {
Config config = parseConfig(args);
List<Module> modules = new ArrayList<>();
modules.add(...); // application modules

String fooModuleName = config.get("foo_module");
Class<? extends Module> moduleClass =
Class.forName(fooModuleName).asSubclass(Module.class);
modules.add(moduleClass.newInstance());

Injector injector = Guice.createInjector(modules);
injector.getInstance(MyApplication.class).run();
}

当然,您也可以使用您喜欢的任何其他机制来选择要安装的模块。在许多情况下,您甚至不想反射(reflection)地这样做,您可以在更改构建依赖项的同时简单地更改代码。

关于java - Guice 中的绑定(bind) : Compile time dependencies,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33401972/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com