6

假设我有一个第三方类如下:

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

现在假设我有一个这样的工厂接口:

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

这个想法是我希望有一个为一个固定的MyObjectFactory构建一个- 也就是说,本质上是从外部在构造函数参数上添加注释。当然,手动实现总是可行的:MyObjectFoo@AssistedBarMyObjectFactory

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

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

但是假设有一些条件需要我让 Guice 构建MyObject实例——例如,方法拦截器。这似乎是“注入注射器”的工作:

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 的方法。

4

2 回答 2

1

首先,由于您所描述的原因,您很少希望MyObject在课堂上传递 around 的实例。你无法控制它们,所以你不能添加@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.

于 2015-06-27T23:25:14.417 回答
-1

实际上是。看看辅助注射

包括

        <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);
于 2015-06-26T07:43:11.077 回答