如何协助非辅助依赖?

时间:2015-06-26 03:39:53

标签: java guice assisted-inject

假设我有第三方课程如下:

public class MyObject {
    @Inject
    public MyObject(Foo foo, Bar bar) { ... }
}

现在假设我有一个像这样的工厂界面:

public interface MyObjectFactory {
    public MyObject build(Bar bar);
}

我的想法是,我希望MyObjectFactory为固定MyObject构建Foo - 也就是说,基本上在@Assisted注释上添加Bar注释来自外部的{1}}构造函数参数。当然,总是可以手动实施MyObjectFactory

public class MyObjectFactoryImpl implements MyObjectFactory {
    @Inject private Provider<Foo> foo;

    @Override
    public MyObject build(Bar bar) { return new MyObject(foo.get(), bar); }
}

但是,让我们说有条件要求我让Guice构建MyObject个实例 - 例如,方法拦截器。这似乎是注射注射器&#34;:

的工作
public class MyObjectFactoryImpl implements MyObjectFactory {
    @Inject private Injector injector;

    @Override
    public MyObject build(Bar bar) {
        Injector child = injector.createChildInjector(new AbstractModule() {
            @Override
            protected void configure() {
                bind(Bar.class).toInstance(bar);
                // Set up method interceptors for MyObject here...
            }
        });
        return child.getInstance(MyObject.class);
    }
}

这听起来很邪恶,但是我想知道是否有任何替代实施和/或让Guice产生工厂impl的方法。

2 个答案:

答案 0 :(得分:1)

首先,由于您描述的原因,您很少希望在班级中传递MyObject的实例。您无法控制它们,因此您无法添加@Assisted注释,无法添加方法拦截器等。此外,当您想要换出第三方库时会发生什么对于不同的实现?

因此,您应该将MyObject包装到另一个对象中。

// **Please** choose better names than this in your real code.
public class MyWrapperBackedByMyObject implements MyWrapperInterface {
    private final MyObject delegate;

    @Inject
    MyWrapperObject(Foo foo, @Assisted Bar bar) {
        delegate = new MyObject(foo, bar);
    }

    @NotOnWeekends  // Example of how you might do method interception
    public void orderPizza() {
       delegate.orderPizza();
    }
}

然后,使用上面描述的命名约定删除代码中对MyObject的所有引用,应该只引用MyWrapperInterface

答案 1 :(得分:-1)

实际上是。看看Assisted Inject

包括

        <dependency>
            <groupId>com.google.inject.extensions</groupId>
            <artifactId>guice-assistedinject</artifactId>
            <version>${guice.version}</version>
        </dependency>

使用辅助

更新注射
public class MyInjectedObject extends MyObject implements MyIntf {
@Inject
public MyObject(Foo foo, @Assisted Bar bar) { super(foo,bar); }
}

您必须再添加一个界面:

public interface MyIntf {}

在您的模块中将通用工厂绑定到您的接口

    install(new FactoryModuleBuilder()
            .implement(MyIntf.class, MyInjectedObject.class)
            .build(MyObjectFactory.class)
);

现在,您可以在任意位置注入MyObjectFactory

MyObject obj = myObjectFactory.build(bar);