2012-08-07 49 views
2

我目前正在尝试在小应用程序中使用Google Guice-3.0。“Assisted”工厂的输出应该是@Singleton

运行此应用程序时,会提示用户输入他的姓名和密码。由于此信息直到运行时才知道,因此我使用AssistedInject来实现我的User实例化。

这是我的UserFactory用武之地。它通过

User user = getInjector().getInstance(UserFactory.class).create(username, password); 
提供的方法

public User create(@Assisted("Username") String username, 
        @Assisted("Password") String password); 

User类是在节目开始时启动一次(在用户输入之后)User

我想在应用程序的整个生命周期中使用这个实例。我已经将范围设置为@Singleton

但问题是,我只能得到错误。吉斯抱怨并呼吁

User user = getInjector().getInstance(User.class); 

时,我没有通过任何变量,如果我添加一个bind(User.class);configure方法,发生错误,没有申报的注释@Assisted(因为你可以把注释中参数前唯一识别它们 - 吉斯可能认为这是其中之一,需要一个依赖于设置(如

bind(String.class).annotatedWith(Assisted.class).toInstance(username); 

但这不是会工作(也许这将通过静态引用,但为什么一件事使用Guice?

下面是一个可以编译的例子。评论的代码导致错误。特别是最后两行对我来说很刺激。

public class KSKB { 

    @Singleton 
    public static class User { 

     public final String name; 

     @Inject 
     public User(@Assisted("Username") String username) { 
      this.name = username; 
     } 

     public static interface Factory { 
      public User create(@Assisted("Username") String username); 
     } 
    } 

    public static void main(String... args) { 
     Injector injector = Guice.createInjector(new AbstractModule() { 

      @Override 
      protected void configure() { 
       install(new FactoryModuleBuilder().build(User.Factory.class)); 
       // bind(User.class); 
      } 

     }); 
     User user = injector.getInstance(User.Factory.class).create("Guice"); 
     System.out.println(user.name); 

     // user = injector.getInstance(User.class); // doesn't work - throws Exception!! 
     // System.out.println(user.name); 
    } 
} 

回答

3

我不认为可以得到你想要的东西,因为你想破坏Guice。

Guice希望自己管理实例及其创建。你可以使用Provider和自定义工厂,如Assisted东西来自己创建对象 - 即使有Guice的支持。但你不能反馈给Guice这些实例。这意味着,你不能告诉Guice使用一个特定的对象作为单例实例。

可能的和简单的解决方案:

  • 创建注入之前确定的用户名和使用bindConstant()模块中绑定的用户名。使用User中的适当对象。然后你可以用@Singleton来标记User,而Guice会尊重它。

  • 用户bind(User.class).toInstance(myUser);。这与第一个提议类似,因为必须在Guice启动并运行之前提取所需的用户名。

  • 不要注入User但一个中间对象UserHolder(或UserManager),其是单元素。该对象具有存储实际用户并获取它的方法。您的初始化代码将获取该持有者(当时为空),并将创建的User放入持有者中。您的应用程序的其他部分也将注入UserHolder


而不花样至少。

+0

谢谢,这有助于。 – Danyel 2012-08-07 15:50:08

+0

Sry,新的Stackoverflow ... 我想补充几个问题: 由于用户有一个密码,我必须用这个密码启动UserModule构造函数并将它存储在一个字段中,然后引用它在配置方法中。如: '最终字符串用户名; final char [] password; public UserModule(String username,char [] password){ this.username = username; this.password = password; } @覆盖公共无效配置(){ 绑定(User.class).toInstance(新的用户(用户名,密码)); }' 另一个问题:为什么我不能将List绑定到LinkedList或某物?在一般的Java类中:[ – Danyel 2012-08-07 15:56:23

+0

关于“新到SO”:没问题,值得欢迎。但你必须明白,这不是一个聊天网站。这意味着,其他用户也希望找到相关的问题来解决他们的问题。只有当不同的问题分解成不同的问题时才有可能。特别是“List”问题已经在这里被问了好几次了。关于第一个项目:重要的是'bind(User.class).toInstance(...)'你正确的事情。用户名和密码如何进入该位置并不重要。但它应该工作。 – 2012-08-07 22:13:27

0

辅助注射的输出不是注射 - 它是自动连线的工厂(可悲的是,这个设施非常可怕地命名)。

AssistedInject生成的是一个工厂 - 该工厂可以是单身。但它是一个工厂,所以它的工作就是创建对象,比如用户对象。 Factory的内部没有设置为让它创建Singleton值对象。价值对象一般来说不是单身对象 - 你在这里用一个“上下文”而不是数据,所以你有一个特殊情况。

此外,您的情况更加特别,因为您希望在guice运行之前预先验证数据库中的数据。此用户完全是上下文,而不是数据,因此不要使用工厂来创建它。手动创建它,如果你需要在guice-bound系统中的其他地方使用它,那么在Guice之外创建它,并将它作为DatabaseCredentials对象或其他类传递到模块中。

要正确地帮助你,我们就需要看到一个更大的设计理念,但我的感觉是,你是不是合作者/服务,价值类型,上下文/配置等之间的差别清晰地思考这种混淆很大程度上是因为“用户”这个词在这里超载了。是的,这是一个“用户”,但数据库用户是不一样类型的用户为系统中的其它用户 - 即使是同样的结构,这意味着不同的东西,有一个不同的生命周期等

相关问题