简体   繁体   中英

How to avoid Google guice injector getInstance() repetative calls due to null?

I have recently started using Google guice DI framework and am quite new to it. I am facing below problem - @inject returns null always and have to call injector to inject various references.

This is my AbstractModule class


public class AppModule extends AbstractModule {

    private static final Injector injector = Guice.createInjector(new AppModule());

    private final Vertx vertx = Vertx.vertx(new VertxOptions().setMetricsOptions(
            new DropwizardMetricsOptions().setEnabled(true)
    ));

    private final com.test.reactivex.db.service.DBService dbService;

    public AppModule() {

        this.dbService = DBService.createProxy(this.vertx, DB_SERVICE_ADDRESS);
    }

    @Override
    protected void configure() {
        bind(Vertx.class).toInstance(this.vertx);
        bind(EventBus.class).toInstance(this.vertx.eventBus());
        bind(FileSystem.class).toInstance(this.vertx.fileSystem());
        bind(SharedData.class).toInstance(this.vertx.sharedData());
        bind(com.test.reactivex.db.service.DBService.class).toInstance(this.dbService);
        bind(AppConfig.class).toProvider(AppConfigProvider.class).in(Singleton.class);
        //requestStaticInjection(AppDependenciesInjector.class);
        logger.info("Google guice module configuration done");
    }

    @Provides
    public static AppConfig appConfig() {
        return injector.getInstance(AppConfig.class);
    }

    public static Injector getInjector() {
        return injector;
    }
}

This is how I am using injector to inject dependencies, but problem is that I have to use injectors again.

public class GraphQLRouter {

    @Inject 
    private static AppConfig config;

    @Inject
    private com.test.reactivex.auth.service.DBService dbService;

    public GraphQLRouter() {
    // below code I want to avoid
        if (dbService == null) {
            dbService = AppModule.getInjector().getInstance(com.test.reactivex.auth.service.DBService.class);
        }
    }

    //below code I want to avoid
    static {
        if (config == null)
            config = AppModule.getInjector().getInstance(AppConfig.class);
    }

This is going to be a terrible answer off the bat, but I'll modify it as more information comes in. The important piece here is that:

1) Your GraphQLRouter class is using field based injection due to the @Inject being on the field, one of those fields is static, which means you're breaking it up even more.

2) You're then attempting to use the dbService in your constructor, that's just never going to work - it's always going to be null.

It all depends on where you're using it. I don't know (pretty much anything) about VertX, so if you need more with regards to that I'll have to do some googling, but you should not mix up all the different types of injections (field, constructor, static).

At a minimum you can use:

@Inject
public GraphQLRouter(AppConfig config, DBService dbService) {
    this.config = config;
    this.dbService = dbService;
}

At this point you're in a better point for the purpose of testing, but we're still missing where you're creating the instance from.

Edit

I did a little reading on Vert.x and had some ideas, they all involve pulling the line

private static final Injector injector = Guice.createInjector(new AppModule());

out of the AppConfig and into your public static void main(String[] args) {} method. Are you using Verticals? Or are you using Vert.x without verticals? Apparently you can do it, but there is no real information on how you would do it (so I'll assume the former). Again, this is just an idea, but you need to move the injector up:

public class RandomVerticle extends AbstractVerticle {

  @Inject
  private GraphQLRouter router;

  @Override
  public void start() {
     // use router
  }
}

public class Application {
   public static void main(String[] args) {
       private static final Injector injector = Guice.createInjector(new AppModule());

       Vertx vertx = injector.getInstance(Vertx.class);
       vertx.deployVerticle(injector.getInstance(RandomVerticle.class));
   }
}

This would require that you provide some kind of binding to the Verticles, which you should probably do anyhow. The documentation talks about being able to use a VerticleFactory which you could implement yourself so that:

vertx.deployVerticle("guice:com.example.SomeVerticle");

was run through something like a:

public class GuiceVerticleFactory implements VerticleFactory {
   public GuiceverticleFactory(Injector injector) {
       this.injector = injector;
   }
}

so you can inject the verticles during creation, but again, I didn't look into the Factory very much, so who knows.

Hopefully it helps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM