Как создать несколько экземпляров одного типа с помощью Google Guice - PullRequest
0 голосов
/ 29 октября 2018

Мы использовали каркас Google Guice для внедрения зависимостей. Мне нужно создать несколько интерфейсов в Java.

Выполнение начинается здесь: класс KfhRecordValidator.java в следующем коде:

public class KfhRecordValidator implements RequestHandler<Request, Response> {
       public Response handleRequest(Request request, Context context) 
        {
     // Resolve the necessary dependencies, and process the request.
       Injector injector = Guice.createInjector(new 
                      DependencyModule());
            Processor processor = 
                 injector.getInstance(Processor.class);
              return processor.process(request, context);
}}

Класс процесса имеет ссылку на класс RecordValidationHelper, а внедрение выполняется через конструктор. IRecordValidationService.java - интерфейс, имеющий метод validate.

public interface IRecordValidationService {
              void validate(Record record) throws ValidationException;}
* Процессор класса

имеет один метод с именем process, который вызывается в классе RecordValidationHelper.

class Processor {
   private final RecordValidationHelper recordValidationHelper;
@Inject
@SuppressWarnings({"WeakerAccess"})
public Processor(IRecordValidationService recordValidationService, 
IRecordService<ErrorRecord> recordService,
                 S3UtilsInterface s3Utils, IEnvironmentVariableReader 
                 environmentVariableReader) {
                 this.recordValidationHelper = new 
                 RecordValidationHelper(recordValidationService);
                 this.errorRecordHelper = new 
                 ErrorRecordHelper(recordService, environmentVariableReader);
}

public Response process(Request request, @SuppressWarnings("unused") Context context) {

    // Validate records
    List<LambdaRecord> records = recordValidationHelper.processRecords(request.getRecords());}

Класс DependencyModule.java extneds Класс AbstractModule для внедрения Guice, в котором есть метод configure.

class DependencyModule extends AbstractModule {
@Override
protected void configure() {
    String validationType = System.getenv("ValidationType");

    validationType= validationType.toLowerCase(Locale.ENGLISH);

    String valType[]= validationType.split(",");
    int length= valType.length;

    for(int i=0;i<length;i++){

        switch(valType[i]){
         case "json":
             bind(IRecordValidationService.class).to(JsonValidationService.class);
             break;
         case "avro":
             bind(IRecordValidationService.class).to(AvroSchemaValidationService.class);
             break;
         case "clientlogging":
             bind(IRecordValidationService.class).to(ClientLoggingValidationService.class);
             break;
         case "servicelogs":
             bind(IRecordValidationService.class).to(ServiceLoggingValidationService.class);
             break;
         default:
             throw new UnsupportedOperationException(String.format("Encountered an unsupported ValidationType of '%s'.", valType[i]));
        }

    } } }

Так что проблема в том, что если я получаю тип проверки как AVRO, JSON, тогда он привязывает IRecordValidationService к соответствующему классу JsonValidationService / AvroSchemaValidationService. Мне нужно создать несколько экземпляров для этого, но он поддерживает только один экземпляр за раз. Ниже приведен класс RecordValidationHelper.java

открытый класс RecordValidationHelper extends AbstractModule { private final IRecordValidationService recordValidationService;

@Inject
public RecordValidationHelper(IRecordValidationService recordValidationService) {
    this.recordValidationService = recordValidationService;
}

public List processRecords (Список requestRecords) { Список записей = новый ArrayList <> ();

    for (RequestRecord record : requestRecords) {
        try {

            Record domainRecord = new Record();
            domainRecord.setKey(record.getRecordId());
            domainRecord.setValue(new String(Base64.getDecoder().decode(record.getData())));

            // Use the injected logic to validate the record.
            ((IRecordValidationService) 
           recordValidationService).validate(domainRecord);}
           catch (ValidationException ex) {}}}
           return records;}

Любой, кто имеет представление о том, как это следует реализовать, чтобы получить несколько экземпляров, подходящих для этого.

1 Ответ

0 голосов
/ 29 октября 2018

Использование @Named привязок

В вашем DependencyModule, связывайтесь, используя имена:

bind(IRecordValidationService.class)
  .annotatedWith(Names.named("json"))
  .to(JsonValidationService.class);
bind(IRecordValidationService.class)
  .annotatedWith(Names.named("avro"))
  .to(AvroSchemaValidationService.class);
bind(IRecordValidationService.class)
  .annotatedWith(Names.named("clientlogging"))
  .to(ClientLoggingValidationService.class);
bind(IRecordValidationService.class)
  .annotatedWith(Names.named("servicelogs"))
  .to(ServiceLoggingValidationService.class);

Тогда у вашего инженера:

@Inject
public RecordValidationHelper(
    @Named("json") IRecordValidationService jsonValidation,
    @Named("avro") IRecordValidationService avroValidation,
    @Named("clientlogging") IRecordValidationService clientLoggingValidation,
    @Named("servicelogs") IRecordValidationService serviceLogsValidation,
  ) {
    this.jsonValidation = jsonValidation;
    this.avroValidation = avroValidation;
    this.clientLoggingValidation = clientLoggingValidation;
    this.serviceLogsValidation = serviceLogsValidation;
}

См. Вики-страница Guice's BindingAnnotation для получения дополнительной информации.

...