Osgi guice-运行时选择不同的提供程序

Osgi guice-运行时选择不同的提供程序,osgi,guice,Osgi,Guice,我想在不停止JVM的情况下更改运行时使用的提供程序。例如,这不是我正试图做的,但是这个想法是一样的:比如,我想在运行的应用程序中间从Amazon S3切换到谷歌云存储。 这是我可以在guice内做的事吗 我必须在运行时提供所有JAR,并在启动时配置所有模块。然后,在应用程序启动之后,我必须使用一个提供程序来确定要注入@startup的实例,以及稍后它发生变化的时间 或者,在更新配置后重新启动应用程序是否更好,然后系统将继续该配置,如果需要更改,应用程序将再次需要重新启动 OSGI能帮上忙吗?你不

我想在不停止JVM的情况下更改运行时使用的提供程序。例如,这不是我正试图做的,但是这个想法是一样的:比如,我想在运行的应用程序中间从Amazon S3切换到谷歌云存储。 这是我可以在guice内做的事吗

我必须在运行时提供所有JAR,并在启动时配置所有模块。然后,在应用程序启动之后,我必须使用一个提供程序来确定要注入@startup的实例,以及稍后它发生变化的时间

或者,在更新配置后重新启动应用程序是否更好,然后系统将继续该配置,如果需要更改,应用程序将再次需要重新启动


OSGI能帮上忙吗?

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

在您的模块中

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
  }
}
某处

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
  }
}
类切换CloudProvider实现提供程序{
@注入@Named(“谷歌”)提供商googleCloudProvider;
@注入@Named(“amazon”)提供者amazonCloudProvider;
@注入配置;//用作交换机“指挥官”
公共云get(){
开关(configuration.getCloudName()){
案例“google”:返回googleCloudProvider.get();
案例“amazon”:返回amazonCloudProvider.get();
违约:
//不管你想要什么,通常都是例外。
}
}
}
或在模块中的提供程序方法中

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
  }
}
@提供
云提供云(
@命名(“谷歌”)提供商google CloudProvider,
@命名(“亚马逊”)提供商amazonCloudProvider,
配置(配置){
开关(configuration.getCloudName()){
案例“google”:返回googleCloudProvider.get();
案例“amazon”:返回amazonCloudProvider.get();
违约:
//不管你想要什么,通常都是例外。
}
}
用法

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
  }
}
class-Foo{
@injectprovider cloudProvider;//不要直接注入云,否则在出现更改时将无法获得更改。
公共空白栏(){
Cloud=cloudProvider.get();
//使用云
}
}

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

在您的模块中

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
  }
}
某处

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
  }
}
类切换CloudProvider实现提供程序{
@注入@Named(“谷歌”)提供商googleCloudProvider;
@注入@Named(“amazon”)提供者amazonCloudProvider;
@注入配置;//用作交换机“指挥官”
公共云get(){
开关(configuration.getCloudName()){
案例“google”:返回googleCloudProvider.get();
案例“amazon”:返回amazonCloudProvider.get();
违约:
//不管你想要什么,通常都是例外。
}
}
}
或在模块中的提供程序方法中

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
  }
}
@提供
云提供云(
@命名(“谷歌”)提供商google CloudProvider,
@命名(“亚马逊”)提供商amazonCloudProvider,
配置(配置){
开关(configuration.getCloudName()){
案例“google”:返回googleCloudProvider.get();
案例“amazon”:返回amazonCloudProvider.get();
违约:
//不管你想要什么,通常都是例外。
}
}
用法

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
  }
}
class-Foo{
@injectprovider cloudProvider;//不要直接注入云,否则在出现更改时将无法获得更改。
公共空白栏(){
Cloud=cloudProvider.get();
//使用云
}
}

好的,这是有道理的。这是个好主意吗?我想我实现它的方法是避免将自己限制在2或3个,等等。我想我可以在这里使用multibinder查找每个实现,然后通过从列表中选择与配置匹配的正确实现(或在该点引发异常)来确定我想要哪个实现。@WalterWhite是的,这是个好主意,在这里使用多重绑定也很好。考虑到问题中的任何内容都不允许我在Guice中评估您的级别,我不认为最好将其提出来,但是是的,如果您现在能够做到这一点,多绑定完全是最好的工具。我在这里只强调,如果某个云具有非单例作用域,您需要使用
Provider
s来避免意外。因此,您应该插入一个
映射
。注意,这只在Guice 4之后才起作用。好的,这是有意义的。这是个好主意吗?我想我实现它的方法是避免将自己限制在2或3个,等等。我想我可以在这里使用multibinder查找每个实现,然后通过从列表中选择与配置匹配的正确实现(或在该点引发异常)来确定我想要哪个实现。@WalterWhite是的,这是个好主意,在这里使用多重绑定也很好。考虑到问题中的任何内容都不允许我在Guice中评估您的级别,我不认为最好将其提出来,但是是的,如果您现在能够做到这一点,多绑定完全是最好的工具。我在这里只强调,如果某个云具有非单例作用域,您需要使用
Provider
s来避免意外。因此,您应该插入一个
映射
。请注意,这仅在Guice 4之后起作用。