Java 如何在不破坏Guice AOP方法拦截的情况下,在Guice注入中提供参数?

Java 如何在不破坏Guice AOP方法拦截的情况下,在Guice注入中提供参数?,java,aop,guice,factory-pattern,Java,Aop,Guice,Factory Pattern,我有一种情况,我需要使用Guice 3.0来实例化我的对象,但其中一个值可能会随着每个实例而改变。我无法绑定该值的类型,在需要创建实例之前我不知道 例如: public class Foo { public Foo(Bar bar, Baz baz) {...} } 我想让Guice插入条参数,但在需要Foo之前,我不知道Baz。该值也不是特定于范围的(例如RequestScope) 我希望这个对象完全由Guice实例化的全部原因是因为我需要方法拦截。在Guice中,“手动构造的实例不

我有一种情况,我需要使用Guice 3.0来实例化我的对象,但其中一个值可能会随着每个实例而改变。我无法绑定该值的类型,在需要创建实例之前我不知道

例如:

public class Foo {
    public Foo(Bar bar, Baz baz) {...}
}
我想让Guice插入
参数,但在需要
Foo
之前,我不知道
Baz
。该值也不是特定于范围的(例如RequestScope)

我希望这个对象完全由Guice实例化的全部原因是因为我需要方法拦截。在Guice中,“手动构造的实例不参与AOP”

我曾尝试使用
提供程序
执行此操作,但这只允许我使用
public Foo get(){…}

必须为
Baz
的每个可能值创建一个提供程序,这将是一个配置噩梦,因此我不能简单地在FooProvider的构造函数中定义
Baz

我觉得我错过了一些基本的东西。也许是因为这是我在周五做的最后一件事。任何想法都将不胜感激

编辑:下面使用“辅助注射”的答案似乎只有在您能够编辑
Foo
的源代码时才有效<代码>Foo在某些情况下实际上可能超出我的控制范围。如果我自己创建实例(即实现我自己的工厂),那么Guice AOP方法拦截器似乎永远都不知道该对象。

看起来“辅助注入”可能是一个解决方案:

除非如果您没有权限对
Foo
的构造函数进行注释,否则它将不起作用

编辑:我发现我可以通过扩展类型并将它们添加到我希望使用的构造函数中来添加辅助注入注释:

public class AssistedFoo extends Foo {
    @AssistedInject
    public AssistedFoo(
        Bar bar,
        @Assisted Baz baz) {
        super(bar, baz);
    }
}
然后在辅助注射注册中使用此扩展实现:

public interface FooFactory {
    Foo create(Baz baz);
}

//...

install(new FactoryModuleBuilder()
    .implement(Foo.class, AssistedFoo.class)
    .build(FooFactory.class));

只有当您无权更改
Foo
时,才需要额外的继承类。显然,如果类是
final

的话,这种变通方法就不起作用了。如果您不能使用辅助注入来创建工厂,您可以编写自己的工厂实现:

// same as for Assisted Inject
public interface FooFactory {
  Foo createFoo(Baz baz);
}

public class FooFactoryImpl implements FooFactory {
  private final Bar bar;

  @Inject
  public FooFactoryImpl(Bar bar) {
    this.bar = bar;
  }

  public Foo createFoo(Baz baz) {
    return new Foo(bar, baz);
  }
}
然后只需将(FooFactory.class.)绑定到(FooFactoryImpl.class)并在需要创建
Foo
s的任何位置注入
FooFactory

编辑:

您可以做一个非常尴尬的变通方法(这将允许方法拦截
Foo
):

  • bind(Foo.class).toConstructor(…)
  • 定义并绑定所述的
    SimpleScope
    范围
  • bind(Baz.class).in(BatchScoped.class)
  • 提供程序
    SimpleScope
    注入到要创建
    Foo
    s的类中
然后:


如果方法不是
私有的
,您甚至可以对此类方法使用方法拦截来处理作用域。。。虽然这可能不是一个好主意,因为如果您根本不在方法中使用参数,这会让人困惑,但它必须在那里工作。

如果我无法将
@辅助的
注释添加到
Baz
参数,该怎么办?e、 g.当我不控制
Foo
的源代码时,只需编写自己的
FooFactory
类,将
Bar
注入其中,然后让它公开一个采用
Baz
参数的方法。然后,该方法可以
返回新的Foo(bar,baz)
。辅助注入所能做的(或多或少)就是使您不必编写直接的实现。这实际上回到了我开始时的情况,但Guice不允许在它没有创建的对象上使用方法拦截器(Guice AOP)。看起来我可能会遇到两个特性的限制冲突的情况。是的,听起来你可能有。我更新了我的答案,提出了一个解决方案,如果你真的需要让方法拦截工作起来,你可以尝试。范围的有趣用法。对其他人来说似乎有点沉重和/或难以跟随。这表明Guice的人可能有机会在这里添加一些机制。@McCamey:是的,我认为这是一个相当丑陋的黑客行为!我认为一个更好的解决方案是在
Foo
上不能使用方法拦截。其中一个选项可能是创建您自己的(可拦截和辅助注入)类来包装
Foo
,并公开您需要的方法。如果您查看另一个答案,我可以通过从
Foo
导入来获得辅助注入。这使我能够控制构造函数注释。@McCamey:是的,对于任何可以扩展的类来说,这都是一个很好的解决方案。
public Foo someMethod(Baz baz) {
  simpleScope.enter();
  try {
    simpleScope.seed(Baz.class, baz);
    /*
     * We're in the scope for Baz, so it can be injected normally into Foo
     * right now.
     */
    return fooProvider.get();
  } finally {
    scope.exit();
  }
}