Guice运行时依赖参数重新注入

时间:2011-10-03 22:51:08

标签: java guice

关于Guice的问题。我还在学习它,但我能理解基础知识。

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

假设我的情况与图片类似(网上有类似的例子)。

enter image description here

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

enter image description here

新的类源是:

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有帮助,但我怎样才能将对象注入?

此问题是否有更多动态解决方案?

感谢。

3 个答案:

答案 0 :(得分:4)

MPierce同意了。我试着解释一下我将问题想象出来的方式(如果我错了,你可以纠正我)。

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

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

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

注入Container / Injector的任何动态(运行时)参数基本上都是,迫使你结束对象图

例如,我们有以下设计:

enter image description here

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

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

enter image description here

但是,再一次,你强迫设计,突然, EmailDispatcher有太多的责任。它可以在这样的环境中使用,你没有很多基础设施类。

enter image description here

如果您在第三个示例图片中有类似的设计,则无法使用Injector / Container来获取NextService3实例(也不会低于EmailDispatcher的级别)。

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

呼。

正确?

答案 1 :(得分:1)

问题的一部分取决于你如何解决'假'是你要为皮带字段设置的东西。这是来自配置数据还是什么?

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

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

如果你能澄清布尔来自何处,它将帮助我理解适用的方法类型。

答案 2 :(得分:1)

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