Совет: принудительное внедрение привязки в качестве поставщика - PullRequest
3 голосов
/ 01 августа 2011

Я ищу способ заставить определенные привязки Guice вводиться только как провайдеры. Например, когда есть конфигурация типа

interface ResultLogger {
    void log(String resultAsString);
}

class ResultLoggerProvider implements Provider<ResultLogger> {
    // ...
}

class ResultDisplayModule extends AbstractModule {
    @Override
    protected void configure() {
        bind(ResultLogger.class).toProvider(ResultLoggerProvider.class);
    }
}

Я хотел бы иметь возможность настроить мой модуль так, чтобы такой класс, как

@Singleton
class ResultParser {
    private final Provider<ResultLogger> loggerProvider;

    @Inject
    public ResultParser(Provider<ResultLogger> loggerProvider) {
        this.loggerProvider = loggerProvider;
    }
}

может быть вставлен просто отлично, но реализация, как

@Singleton
class ResultParser {
    private final ResultLogger resultLogger;

    @Inject
    public ResultParser(ResultLogger resultLogger) {
        this.resultLogger = resultLogger;
    }
}

должен вызвать исключение RuntimeException, уведомляющее разработчика о том, что ResultLogger доступно только через провайдера. В идеале исключение должно быть выдано как можно скорее, например, во время строительства инжектора. Я ищу простой способ добиться этого, используя существующий API в Guice 3.0.

Ответы [ 3 ]

4 голосов
/ 01 августа 2011

Может быть, вы вообще не должны реализовывать Provider и просто иметь

@Singleton
public class ResultLoggerProvider {
   public ResultLogger get() {...}
   // ...
}

@Singleton
class ResultParser {
   private final ResultLoggerProvider loggerProvider;

   @Inject
   public ResultParser(ResultLoggerProvider loggerProvider) {
      this.loggerProvider = loggerProvider;
   }
}

и удалите другие привязки.

1 голос
/ 01 августа 2011

Я думаю, что это не правильно. Я думаю, вам нужно smt, как

interface ResultLogger {
    void log(String resultAsString);
}
class ResultLoggerWrapper implements ResultLogger {
      @Inject @Named("day") ResultLogger dayLogger;
      @Inject @Named("night") ResultLogger nightLogger;
      public void log(String resultAsString){
           if(isDay()) {
                 dayLogger.log(resultAsString)
           } else {
                 nightLogger.log(resultAsString)
           }
      }
}  

bind(ResultLogger.class).to(ResultLoggerWrapper.class);
0 голосов
/ 01 августа 2011

Должно работать, чтобы связать провайдера вместо ResultLogger. То есть в вашем модуле

bind(new TypeLiteral<Provider<ResultLogger>>(){}).to(ResultLoggerProvider.class);
...