2011-12-04 38 views
7

我有一个web应用程序使用GIN在入口点注入依赖关系。Guice /杜松子酒。如何注入多个实现

private InjectorService injector = GWT.create(InjectorService.class); 

@GinModules({PlaceContollerInject.class, RootViewInject.class}) 
public interface InjectorService extends Ginjector { 

    RootView getRootView(); 
    PlaceController getPlaceConroller(); 

} 

public class RootViewInject extends AbstractGinModule { 

    @Override 
    protected void configure() { 
    bind(RootView.class).to(RootViewImpl.class); 
    } 
} 

我需要使用不同的RootView实现的移动版本。依赖以下模块

public class RootViewMobileInject extends AbstractGinModule { 

    @Override 
    protected void configure() { 
    bind(RootView.class).to(RootViewMobileImpl.class); 
    } 
} 

中描述的问题是如何选择需要依赖我们有条件是否需要移动或默认版本。 我见过GWT-GIN Multiple Implementations,但还没有找到解决方案,因为Provider违反了依赖关系的链条,Factory Pattern破坏了可测试性。 在“具有Guice的大型模块化Java”视频here (12 minute) Guice的模块注入器作为工厂的替代品提供。所以我的问题是我应该为我的应用程序的移动版和默认版本(如MobileFactory和DefaultFactory)创建不同的Ginjector,否则这将是不好的做法,我应该为所有需要的版本配置一个Ginjector实例。例如像这样的注释绑定。

public class RootViewMobileInject extends AbstractGinModule { 

    @Override 
    protected void configure() { 
    bind(RootView.class).annotatedWith(Mobile.class).to(RootViewMobileImpl.class); 
    } 
} 

,并使用在GWT入口点

​​

@Mobile注释绑定在这样的简化的例子,因为它上面是可能的。但是如果一个应用程序有更多的需要移动和默认版本的依赖。它看起来回到了无法测试的“丑陋”(正如在Guice的演讲中所说的)工厂。 对不起,我的英文。任何帮助表示赞赏。

+1

我只想补充一点,这里的想法和@aldanok的解决方案也可以用于应用程序中的客户端特定定制。特定于客户端:gwt.xml + gin模块+接口实现。 – MeTTeO

回答

9

我相信你会想要使用GWT延迟绑定,使用类替换来绑定不同版本的InjectorService,具体取决于用户代理。这将确保移动版本只有在(并下载)编译的移动实现

因此,您将InjectorServiceDesktop,InjectorServiceMobile,它们都从InjectorService扩展,然后GWT.create(InjectorService.class),并让延迟绑定决定它应该使用哪个实现。与所有版本Ginjector的

http://code.google.com/webtoolkit/doc/latest/DevGuideCodingBasicsDeferred.html#replacement

一个实例似乎不好,因为这意味着两个版本的所有代码总是下载(你肯定不希望下载您所有的桌面视图到您的移动应用程序)

编辑:正如Thomas在注释中指出的那样,由于注入器是生成的类,因此您需要将每个InjectorServiceXXX放入一个简单的持有者类中,该持久类是GWT.create()的InjectorServiceXXX的 ,并使用替换在持有人。

+5

+1,但不能这样工作:您不能同时进行替换和生成,您必须创建包含2个子类的“InjectorServiceHolder”。每个'GWT.create()'是一个不同的'InjectorService'子接口。您使用“持有者”上的替换来选择要使用哪个InjectorService,并且InjectorService子接口上的GWT.create()会触发GIN的代码生成。 –

+0

为更正而欢呼!更新了答案。 – aidanok

+0

谢谢你的回答。我非常同意你的看法,我应该使用不同的投影仪。它非常简单和方便。但是,对于Guice方面的问题,你认为如何处理同样的问题,而没有延迟绑定技术。你更喜欢什么技术来覆盖基本模块 - [Modules.override](http://stackoverflow.com/questions/7314323/how-to-override-binding-in-gin)或只是Java的继承。为什么?还有更多...如何在需要所有版本时配置Ginjector/Injector(比如说DefaultView和LoggedInView)? – trupanka

1

做你想做的事实际上是相当复杂的,因为你的公共注入接口,用你的杜松子酒模块注释,不能指向抽象的杜松子酒模块。您的Ginjector界面指向的杜松子酒模块必须是具体的模块。具体模块不能同时满足多种配置。

所以你要做的是: (a)创建你的Ginjector接口,比如ClientGinjector和Module,ClientModule,用于桌面应用程序。 (b)创建第二个Ginjector接口,比如ClientGinjectorTablet,扩展你在(a)中创建的接口,但是使用指向不同模块的GinModule注释,比如ClientModuletablet。

- 现在,您有两个Ginjecor接口是平板电脑的默认接口和辅助接口,每个接口指向具有自己的Configure()实现的模块。 (c)现在你想创建工厂来获得你的正确的Ginjector实现。你可以这样做,因为你在(a)和(b)中关心的Ginjector有一个共同的demonitador,它是(a)中创建的默认界面。 因此,您使用如下方法创建抽象故障: public abstract ClientGinjector getInjector(); 您创建两个儿童具体类一个获取桌面/默认感应器和另一个获取Tablet Ginjector。 (d)现在您在youtube上配置模块的gwt.xml,就像Google IO一样,解释您应该在运行时为您的每个Ginjector工厂使用GWT延期绑定,在运行时获取所需的设计。 (e)在你的入口点上,第一件事情就是不使用Ginjector,而是使用GWT延迟绑定的Ginjectors工厂。 您可以调用返回ClientGinjector的抽象方法, 您的设置。 (f)最后的史诗失败。即使您使用不同的注射器(一个用于桌面,另一个用于平板电脑),Guice也不会让您绑定两次相同的键(类加注释)。看起来键绑定定义是全局的,只要你有两个模块重新定义相同的键,那就是冒险的结束。

相关问题