【问题标题】:Guice runtime dependency parameters reinjectionGuice 运行时依赖参数重新注入
【发布时间】:2011-10-03 22:51:08
【问题描述】:

关于 Guice 的问题。我还在学习它,但我可以理解基本原理。

这个问题已经在网上被问过几次了,但从来没有一个具体的答案(我找不到)。

假设我遇到了图片上的情况(网上也有类似的例子)。

public class Dog {}

public class Walk implements Walkable {
    private final Dog dog;
    private final boolean leash;

    @Inject
    public Walk(Dog dog, @Assisted boolean leash) {
        this.dog = dog;
        this.leash = leash;
    }

    public void go() {
    }
}

public interface Walkable {
    void go();
}

public interface WalkFactory {
    Walk create(boolean leash);
}

public class AssistedMain {
    public static void main(String[] args) {
        Injector i = Guice.createInjector(new AbstractModule() {
            protected void configure() {

                install(new FactoryModuleBuilder().
                        implement(Walkable.class, Walk.class).
                        build(WalkFactory.class));
            }
        });

        Walk walk = i.getInstance(WalkFactory.class).create(true);
    }
}

这一切都很好。但问题是——我能否以某种方式将该对象实例重新注入到“容器”(注入器)中,以便在依赖此依赖项的类上使用。

所以,让我们添加一个interface Personclass PersonImpl

新的类来源是:

public interface Person {
    void walkDog();
}

public class PersonImpl implements Person {
    private Walkable walkable;

    @Inject
    public PersonImpl(Walkable walkable) {
        this.walkable = walkable;
    }

    public void setWalkable(Walkable walkable) {
        this.walkable = walkable;
    }

    public void walkDog() {
        walkable.go();
    }
}

所以,问题是——我是否能够以某种方式将这个特定实例实际注入到添加的对象中。这是一个简单的例子,但我们可以假设在这个之下有 10 级类。

我找到的解决方案不是很灵活。比如:

Injector i = Guice.createInjector(new SimpleModule(false, dog));

然后绑定到具体实例。这不是很动态。基本上,每次我需要不同的运行时/动态参数时,我都必须重新创建注入器。

Provider<T> 很好,FactoryModuleBuilder 有帮助,但我怎样才能将对象注入回去?

这个问题有更多动态的解决方案吗?

谢谢。

【问题讨论】:

    标签: java guice


    【解决方案1】:

    MPierce - 同意。我会尝试解释我想象问题的方式(如果我错了,你可以纠正我)。

    最初源自“服务定位器”模式,它可以管理的不仅仅是服务的想法至少可以说是乐观的。

    我们可以将应用程序拆分为服务和数据类,或者您可以说我们有应用程序和基础架构代码 - “依赖注入”,一本很棒的书。

    因此,基本上,依赖注入和依赖注入框架通常都很棒。 用于解决基础架构或“服务”代码。

    注入到容器/注入器中的任何动态(运行时)参数基本上迫使您结束对象图

    例如,我们有以下设计:

    EmailMessage 是一个运行时参数。它可以被“注入”到 Container/Injector 之外的电子邮件服务中,但它会结束对象图。 如果我们想请求 EmailDispatcher,在我们将 EmailMessage 注入到 EmailService(我重复一遍,在注入器外部完成)之后,我们无法再从注入器中获取 EmailDispatcher。

    然后,您可以重新设计模型,使其“适合”动态参数的 Container/Injector 概念。

    但话又说回来,你强加了设计,突然间,EmailDispatcher 的职责太多了。它可以在没有很多基础设施类的情况下使用。

    当您有第三张示例图片中的设计时,您不能使用 Injector/Container 为您获取 NextService3 实例(也不能低于 EmailDispatcher 的级别)。

    问题是 - 如果你有任何动态(运行时)参数,你只能对需要动态参数的类之上的类使用依赖注入,你可以忘记下面的类。

    呼。

    正确吗?

    【讨论】:

      【解决方案2】:

      部分问题取决于您如何解决“假”是您要为皮带字段设置的内容。这是来自配置数据还是什么?

      提供者方法可能会有所帮助...

      class FooModule extends AbstractModule {
      ...
          @Provides
          Walkable getWalkable(Dog dog) {
              boolean leash = getBooleanFromSomewhere();
              return new Walk(dog, leash);
          }
      }
      

      如果您能澄清该布尔值的来源,它将帮助我了解适用的方法类型。

      【讨论】:

      • 皮带是应用程序中某处的动态参数。可以说这个参数是由用户在应用程序中提供的(有一个皮带复选框:))。用户可以选中和取消选中该复选框,并期望一个人在带或不带皮带的情况下遛狗。 “问题”是该参数是动态的,并且需要“重新注入”到“容器”中,因此“基础设施”对象图可以根据该参数实例化对象。这是一个简单的示例,假设您有 30 个用户,并且您希望根据登录情况为每个用户获取 UserTransaction。
      • 我明白了。那么,也许注射不是解决此问题的正确工具。当定义注入的参数由用户数据驱动时,注入通常很尴尬。 (啊,我不能在评论中添加换行符?)您可以尝试使用请求范围的注入,其中注入的内容取决于您通过检查经过身份验证的用户确定的参数,或者稍微重构您的 API 以允许“牵引”作为方法参数而不是对象中的字段提供。我意识到,这并不是您真正想要的答案,但我认为您正在扩展 IoC 做得好的极限。
      【解决方案3】:

      您可以使用custom scopes,就像使用 guice servlet 时一样。这样你就可以创建你的实例,然后在注入器中播种它。

      【讨论】:

      • 一个好主意,但不能真正解决问题。问题是动态重新注入,在“将注释绑定到实现”中,示例从注入器中实例化实例。通过在初始化之前将对象传递给 guice 可以实现相同的功能(这将更加动态)。关键是,自定义范围很有用,但在这种情况下却没有——我仍然在注入器中有一个实例化,这意味着它是一个静态初始化的容器,实际上并没有给我任何对象注入的灵活性。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-12-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-07-09
      • 2012-11-23
      相关资源
      最近更新 更多