2017-08-18 51 views
0

我想在运行时更改我正在使用的提供者,而不必停止JVM。例如,这不是我想要做的,但这个想法是一样的:比如说,我想在正在运行的应用程序中间从Amazon S3切换到Google Cloud存储。guice - 在运行时选择不同的提供者

这是我能做的事情吗?

我将不得不在运行时提供所有jar并在启动时配置所有模块。然后,稍后一旦启动应用程序,我将不得不使用一个提供程序,该提供程序可以确定将哪个实例注入@ startup以及稍后何时更改。

或者,更新配置后重新启动应用程序会更好,然后系统会继续进行配置,如果需要更改,应用程序将需要重新启动。

OSGI会帮忙吗?

回答

2

你不需要任何额外的东西:Guice可以开箱即用。但是......您必须使用Providers而不是直接实例。

在你的模块

bind(Cloud.class) 
    .annotatedWith(Names.named("google")) 
    .to(GoogleCloud.class); 
bind(Cloud.class) 
    .annotatedWith(Names.named("amazon")) 
    .to(AmazonCloud.class); 
bind(Cloud.class) 
    .toProvider(SwitchingCloudProvider.class); 

某处

class SwitchingCloudProvider implements Provider<Cloud> { 
    @Inject @Named("google") Provider<Cloud> googleCloudProvider; 
    @Inject @Named("amazon") Provider<Cloud> amazonCloudProvider; 
    @Inject Configuration configuration;  // used as your switch "commander" 
    public Cloud get() { 
    switch(configuration.getCloudName()) { 
     case "google": return googleCloudProvider.get(); 
     case "amazon": return amazonCloudProvider.get(); 
     default: 
     // Whatever you want, usually an exception. 
    } 
    } 
} 

或者在您的模块中提供的方法

@Provides 
Cloud provideCloud(
    @Named("google") Provider<Cloud> googleCloudProvider, 
    @Named("amazon") Provider<Cloud> amazonCloudProvider, 
    Configuration configuration) { 
    switch(configuration.getCloudName()) { 
    case "google": return googleCloudProvider.get(); 
    case "amazon": return amazonCloudProvider.get(); 
    default: 
     // Whatever you want, usually an exception. 
    } 
} 

用法

class Foo { 
    @Inject Provider<Cloud> cloudProvider; // Do NOT inject Cloud directly or you won't get the changes as they come up. 
    public void bar() { 
    Cloud cloud = cloudProvider.get(); 
    // use cloud 
    } 
} 
+0

好的,这是有道理的。这是一个好主意吗?我认为我实现它的方式是避免将自己限制在2或3等。我想我可以在这里使用multibinder来查找每个实现,然后通过从列表中选择正确的匹配配置(或在此时抛出异常)。 – Walter

+1

@WalterWhite是的,这是一个好主意,在这里使用多重绑定也很好。考虑到这个问题中没有什么能够让我评估你在Guice的水平,我不认为最好把它提出来,但是,如果你现在可以走这么远,Multibinding就是最好的工具。我只会坚持认为,如果其中一个云具有非单例范围,则需要使用“提供者”来避免意外。所以你应该注入一个'Map >'。请注意,这只有在Guice 4以后才有效。 –

相关问题