2

我想为其中一个组件使用 Guice 的静态实例方法(非托管 bean 应该能够访问此类)。我创造了这样的东西:

public class LookupService {

   @Inject
   private static Provider<Injector> injector = null;

   private final ILookup<IWS> lookup;

   @Inject
   public LookupService(ILookup<IWS> lookup) {
      this.lookup = lookup;
   }

   public static LookupService instance() {
     return injector.get().getInstance(LookupService.class);
   }

   public <T extends IWS> T lookup(Class<T> localInterface) {
      return lookup.lookup(localInterface);
   }

}

你觉得这个设计怎么样?对此还有其他想法吗?(从非托管对象访问托管 bean)

4

1 回答 1

6

基本上,您正在寻找的模式称为“请求静态注入”,并且有一个专用于它的 Binder 方法。一旦你把它写下来,你的代码看起来很像Guice 文档中的这个例子

public class MainModule extends AbstractModule {
  @Override public void configure() {
    requestStaticInjection(LookupService.class);
  }
}

public class LookupService {

  /** This will be set as soon as the injector is created. */
  @Inject
  static Provider<LookupService> provider = null;

  private final ILookup<IWS> lookup;

  @Inject
  public LookupService(ILookup<IWS> lookup) {
    this.lookup = lookup;
  }

  public static LookupService instance() {
    return provider.get();
  }

  public <T extends IWS> T lookup(Class<T> localInterface) {
    return lookup.lookup(localInterface);
  }
}

几点注意事项:

  • 虽然您仍然可以将您的字段设置为private,但请记住,这意味着如果没有 Guice 的私有字段访问魔法,您将无法在测试(或将来的非 Guice 使用)中设置它。使用注入字段时,我们经常将它们设为包私有,然后将测试放在同一个包中。

  • 静态注入通常被视为仅在迁移到 Guice 或使用无法更改的其他代码时才认可的东西。如果可能,尽量避免全局状态——即使这意味着FooBean只制作数据并创建一个注入的FooBeanService.

  • 即使你可以在Injector任何你想要的地方注入一个,你可能会发现如果你只是注入一个更容易测试Provider<LookupService>。只有在运行时才知道需要什么类型的情况下才注入 an Injector——例如,如果您通过将类文字传递给注入器来获取实例来LookupService.lookup(...)使用 an来实现。Injector

  • 实际上,从这里很难说,但ILookup似乎很像服务定位器模式,它解决了 Guice 通过依赖注入解决的确切问题类型!如果是这种情况,您不妨重写 ILookup 以使用 Guice:只需删除对的调用LookupService.instance().lookup(Foo.class),而是创建一对匹配的@Inject static Provider<Foo> fooProviderand requestStaticInjection(FooUser.class)

希望有帮助!

于 2012-10-31T03:08:19.807 回答