2012-10-30 67 views
2

我想用Guice作为其中一个组件的非静态实例方法(非托管bean应该可以访问这个类)。我创造了这样的事情:Guice的实例方法

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)

回答

6

基本上,您要查找的模式称为“请求静态注入”,并且存在Binder method dedicated to it。一旦你这样做了,你的代码看起来很像this example from the Guice docs

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时,或者当您使用其他代码无法更改时才需要认可。如果可能,尽量避免全局状态 - 即使这意味着仅生成FooBean数据并创建注入FooBeanService

  • 尽管您可以随时随地注入Injector,但如果您只是简单地注入Provider<LookupService>,您可能会发现测试更容易。如果在运行时不知道需要什么类型,则只注入Injector - 例如,如果通过将类文字传递到注入器以获取实例来实现LookupService.lookup(...),则使用Injector

  • 事实上,很难从这里说出来,但ILookup似乎很像Service Locator pattern,它解决了Guice用依赖注入解决问题的确切类型!如果是这样的话,你可以重写ILookup来使用Guice:只需删除对LookupService.instance().lookup(Foo.class)的调用,而是创建一对匹配的@Inject static Provider<Foo> fooProviderrequestStaticInjection(FooUser.class)

希望帮助!

+0

好的答案! +1 –

+0

感谢您撰写!我有类似的情况,你在第二点(旧代码库)中描述。随着时间的推移,我将尝试迁移到没有静态的方法。 这种方法恕我直言,但测试并没有那么糟糕,但需要Guice集成到测试框架。然后,当你想测试调用'LookupService.instance()'的类时,你需要在测试开始时为它绑定模拟实现。 – sol25

+0

@ sol25请记住,基于Guice的系统测试是很好的,但是你也可能发现单元测试也是非常有用的,尤其是使用_mock_ LookupService的bean测试。放宽静态字段可见性可能会让你完全在大部分测试中跳过Guice。 –