【问题标题】:Proper use of GWT RequestFactory ServiceLocator and DI正确使用 GWT RequestFactory ServiceLocator 和 DI
【发布时间】:2013-12-22 17:01:48
【问题描述】:

我是第一次尝试使用 RequestFactory (RF),并且正在努力实现我的第一个 ServiceLocator

来自RequestContext

// Sign a user in or out of the app.
@ServiceName(
    value="com.myapp.server.DefaultSignInOutService",
    locator="com.myapp.server.DefaultSignInOutServiceLocator"
)
public interface SignInOutService extends RequestContext {
    public Request<String> signIn(SignIn signIn);
    public Request<Void> signOut(SignOut signOut);
}

然后是DefaultSignInOutServiceLocator

public class DefaultSignInOutServiceLocator implements ServiceLocator {
    // I am using Guice-3.0 for server-side DI, and ServiceLocatorModule is an AbstractModule.
    ServiceLocatorModule serviceLocatorModule = new ServiceLocatorModule();

    // Will be initialized by Guice.
    private DefaultSignInOutService signInOutService;

    public DefaultSignInOutServiceLocator() {
        super();

        // Bootstrap DI.
        Injector injector = GWT.createInjector(serviceLocatorModule);

        // injector.getInstance() returns a fully-configured/wired
        // DefaultSignInOutService instance.
        setSignInOutService(injector.getInstance(SignInOutService.class));
    }

    @Override
    public Object getInstance(Class<?> clazz) {
        // I'm trying to use proper DI best practices here, and avoid code like:
        //
        // return new DefaultSignInOutService(true, "Yes", 35);
        //
        // Rather, I'd like to be able to return an already pre-configured service impl:
        return signInOutService;
    }

    // Getters/setters, etc.
}

我的理解ServiceLocators 基本上是服务实现的工厂。如果这是真的,那么如果我将 Guice 用于服务器端 DI,我需要从定位器的构造函数中初始化我的 Guice 模块。但是,如果我需要自己编写任何代码(在应用程序的其他位置)创建DefaultSignInOutServiceLocator 的实例并显式调用其getInstance() 方法,那么我不需要将ServiceLocatorModule 放入@ 987654330@。在这种情况下,我可以有这样的代码:

public class DefaultSignInOutServiceLocator implements ServiceLocator {
    @Injected
    private DefaultSignInOutService signInOutService;

    @Override
    public Object getInstance(Class<?> clazz) {
        return signInOutService;
    }

    // Getters/setters, etc.
}

所以这是我的问题:

  1. ServiceLocator 是否是放置 Guice 模块的合适位置(从而从其中引导 DI)?否则,如何使用正确连接/配置的服务实现注入定位器?
  2. 或者,我只是不明白ServiceLocator#getInstance() 的目的吗?
  3. 如果我在这里的方向是正确的,那么注入的signInOutService 应该是什么“范围”(Spring DI 术语)?它应该是单件还是多件/原型?我是否需要担心这里的线程安全(多个线程获得相同的signInOutService 实例)?还是 GWT 以某种方式确保 RequestFactoryServlet 以线程安全的方式访问定位器?

【问题讨论】:

    标签: java gwt guice requestfactory service-locator


    【解决方案1】:

    ServiceLocators 由ServiceLayerDecorator 实例化,您可以插入自己的。

    ServiceLocators 和它们创建的服务实例几乎是单例(如果可用内存不足,它们可能会被垃圾收集,然后重新创建新实例),因此您应该配置将它们视为您身边的单例,或者至少确保您将它们视为单例(即注入 Providers 以​​获取请求范围的值,例如当前用户)。

    您可以在 https://github.com/tbroyer/gwt-maven-archetypes 找到一个完整的 Maven 原型形式的示例

    【讨论】:

    • 谢谢@ThomasBroyer (+1) - 我今晚回家后会检查你的原型。与此同时,两个快速跟进:
    • (1) 你能确认ServiceLocators 是放置Guice 模块的合适位置吗?还是说我应该实现自己的ServiceLayerDecorator 并将Guice 模块放在那里?
    • 和 (2) ServiceLocator#getInstance(Class&lt;?&gt;) 方法的调用频率是多少?每个 HTTP 请求一次,还是在应用服务器启动时一次?再次感谢!
    • (1) IMO,您应该实现自己的ServiceLayerDecorator。 (2) ServiceLocator#getInstance(Class&lt;?&gt;) 在第一次需要时被调用一次(不是在启动时,而是懒惰地),返回的实例被放入缓存中;当内存变低时,缓存可能会被清除(缓存正在使用SoftReferences),因此稍后可能会再次调用getInstance(这取决于服务实例的生命周期)。请注意,这也适用于 ServiceLocator 实例!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多