2015-10-21 64 views
1

我们的项目设置如下:创建与注入器无关的Guice单例程

1)主模块:包含启动Spark流服务器的驱动程序。它有自己的Guice注射器。

2)当消息进入时,它会转到另一个模块,创建它自己的Guice注入器。

3)该模块使用其他模块中的类,这些模块本身使用从属模块。这些模块中的每一个都创建了自己的Guice注入器,以便它可以独立工作,单独测试等。

以下是一个问题:现在我们需要一个Singleton,但创建为@Singleton的对象绑定到注入器(而不是ClassLoader),所以当喷射器消失时,物体消失。

问题:

1)我们的建筑是坏的吗?我们是不是应该在每个模块中创建一个注入器?

2)我们如何创建一个即使喷油器消失也会保留在ClassLoader中的Singleton?

顺便说一句,我们在Guice上使用Netflix Governator。

注意:回答这个问题被认为是重复的这个问题没有回答如何将顶层模块上创建的“单个”注入器传递给子模块。另外,如果子模块本身没有注入器,我们可以为它们编写独立的单元测试吗?

+0

'Singletons'在Java反模式,因为它们并不像你想象的那样绑定到JVM上,而是绑定到一个'ClassLoader'上,'JVM'实例可以有很多实例并且是一个根本不同的范围。 如果您阅读Guice文档,有一个Module * inheritance *类型的概念,它允许具有父模块范围的子模块*。这是你需要使用的。 –

+0

这个问题有点令我困惑,因为我不知道你的意思是“架构模块”还是“Guice'模块” –

+0

Tavin - “module”是指Maven下的一个模块。每个都有自己的pom.xml,每个都有自己的Guice模块。 – DilTeam

回答

2

问题2的想法是使用一个提供程序,您可以在所有不同的模块中进行绑定。该提供者将访问Guice外部存在的单例。

我制作了一个简单的例子,我可以访问一个静态字段。你可以改变它来使用适合你需要的Singleton模式的实现。

public class SingletonProvider implements Provider<TheSingleton> { 

    private static final TheSingleton instance = new TheSingleton(); 
    @Override 
    public TheSingleton get() { 
     return instance; 
    } 
} 

然后我们结合这给我们不同的模块

public class Module1 extends AbstractModule { 

    @Override 
    protected void configure() { 
     bind(TheSingleton.class).toProvider(SingletonProvider.class); 
    } 
} 
public class Module2 extends AbstractModule { 

    @Override 
    protected void configure() { 
     bind(TheSingleton.class).toProvider(SingletonProvider.class); 
    } 
} 

然后我创建了返回同一实例两个不同的喷油器

public class Test { 
    public static void main(String[] args) { 
     Injector injector1 = Guice.createInjector(new Module1()); 

     TheSingleton instance = injector1.getInstance(TheSingleton.class); 
     System.out.println("instance = " + instance); 

     Injector injector2 = Guice.createInjector(new Module2()); 
     TheSingleton instance2 = injector2.getInstance(TheSingleton.class); 
     System.out.println("instance2 = " + instance2); 


    } 
} 
+0

你保留SingletonProvider中的哪个模块? – DilTeam

+0

@DilTeam提供者不在任何模块中。每个注入器将创建它自己的提供者实例,并使用它来获取TheSingleton.class的实例。您可以将其视为可以在模块之外提供访问的类。 –

+0

您是否在调试器中确认它们确实是相同的对象而不是副本? – DilTeam