无法在 Dropwizard 应用程序中为 Guava Service Manager 创建注入器

Cannot create injector for Guava Service Manager in Dropwizard application

我想使用 Guava 的服务管理器来管理我的 Dropwizard 应用程序中的服务。

ServiceManagerProvider提供服务管理器:

@Singleton
public class ServiceManagerProvider implements Provider<ServiceManager> {
    @Inject
    Set<Service> services;

    public static Multibinder<Service> serviceRegistry(Binder binder) {
        return Multibinder.newSetBinder(binder, Service.class);
    }

    @Override
    public ServiceManager get() {
        return new ServiceManager(services);
    }
}

ManagedGuavaServices 是一个 Managed 对象,它与服务管理器交互以 start/stop 服务:

public class ManagedGuavaServices implements Managed {
    @Inject
    private ServiceManager _serviceManager;

    @Inject
    public ManagedGuavaServices(ServiceManager serviceManager) {
        _serviceManager = serviceManager;
    }

    @Override
    public void start() throws Exception {
        _serviceManager.startAsync();
    }

    @Override
    public void stop() throws Exception {
        _serviceManager.stopAsync();
    }
}

MyModule 是指定 Guice 绑定的模块:

public class MyModule extends DropwizardAwareModule<MyConfig> {
  ...
  @Override
    protected void configure() {
      bind(ServiceManager.class).toProvider(ServiceManagerProvider.class);
      bind(Managed.class).to(ManagedGuavaServices.class).in(Singleton.class);
    }
}

MyApplication是依赖MyModule的Dropwizard应用:

public class MyApplication extends Application<MyConfig> {
  @Inject
  private Managed managedServices;

  ...

  @Override
  public void initialize(Bootstrap<MyConfig> bootstrap) {
    bootstrap.addBundle(GuiceBundle.builder()
                .printDiagnosticInfo()
                .printGuiceBindings()
                .enableAutoConfig(getClass().getPackage().getName())
                .modules(
                        new MyModule()
                )
                .build());
  }

  ...

  @Override
  public void run(MyConfig config, Environment environment) {
    environment.lifecycle().manage(managedServices);
  }
}

似乎一切都已连接在一起,但是当我 运行 应用程序时,我收到错误消息:

java.lang.NullPointerException
    at java.base/java.util.Objects.requireNonNull(Objects.java:221)
    at io.dropwizard.lifecycle.setup.LifecycleEnvironment.manage(LifecycleEnvironment.java:45)
    at com.example.MyApplication.run(MyApplication.java:188)
    at com.example.MyApplication.run(MyApplication.java:60)
    at io.dropwizard.cli.EnvironmentCommand.run(EnvironmentCommand.java:44)
    at io.dropwizard.cli.ConfiguredCommand.run(ConfiguredCommand.java:87)
    at io.dropwizard.cli.Cli.run(Cli.java:78)
    at io.dropwizard.Application.run(Application.java:94)
    at com.example.MyApplication.main(MyApplication.java:70)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at com.webobjects._bootstrap.WOBootstrap.main(WOBootstrap.java:118)

这实质上意味着当应用程序为运行.

时,MZPaymentApplication中注入的managedServices为空

这里有什么问题?它与中的问题相同吗?如果是这样,@PostConstruct 应该在哪里?

问题在于 managedServices 是应用程序中的字段并且不可注入,因为应用程序对象不是由 Guice 配置的(通常在 Dropwizard 中它是通过 new 关键字创建的)。 因此,您应该将 GuiceBundle 实例作为字段存储在 initialize 方法中,然后使用 guiceBundle.getInjector().getInstance()run 方法中访问任何 Guice 绑定,例如:

public class MyApplication extends Application<MyConfig> {

  private GuiceBundle<MyConfig> guiceBundle;

  public static void main(String[] args) throws Exception {
    new MyApplication().run(args);
  }

  @Override
  public void initialize(Bootstrap<MyConfig> bootstrap) {

    guiceBundle = GuiceBundle.builder()
                .printDiagnosticInfo()
                .printGuiceBindings()
                .enableAutoConfig(getClass().getPackage().getName())
                .modules(
                        new MyModule()
                )
                .build();

    bootstrap.addBundle(guiceBundle);
  }

  @Override
  public void run(MyConfig config, Environment environment) throws Exception {
    environment.lifecycle().manage(guiceBundle.getInjector().getInstance(Managed.class));
  }
}