Guice @ Обеспечивает предоставление класса, который зависит от двух параметров - PullRequest
0 голосов
/ 02 ноября 2019

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

public class AWSModule extends AbstractModule {

    @Override
    protected void configure() {
    }

    @Singleton
    @Provides
    public AmazonComprehend getAWSComprehendClient(@Named("materialSet") final String materialSet, 
@Named("region") final String region) {

        return AmazonComprehendClientBuilder.standard().withCredentials(
                new OdinAWSCredentialsProvider(materialSet))
                                            .withRegion(region).build();
    }

}

public class ComprehendHelper {
    private AmazonComprehend amazonComprehend;

    @Inject
    public ComprehendHelper(AmazonComprehend amazonComprehend) {
        this.amazonComprehend = amazonComprehend;
    }

    public void detectLanguage(String sentence) {
        DetectDominantLanguageRequest detectDominantLanguageRequest =
                new DetectDominantLanguageRequest().withText(sentence);    
amazonComprehend.detectDominantLanguage(detectDominantLanguageRequest).getLanguages().stream().forEach(l -> System.out.println(l));
    }

public static void main(String[] args) {
        Injector injector =
                Guice.createInjector(
                        new AWSModule());
        injector.getInstance(ComprehendHelper.class).detectLanguage("best mobile phone");
    }
}

Я не смог передать значения параметров в своем основном классе. Тем не менее я выполнил и получил следующую ошибку:

Exception in thread "main" com.google.inject.ProvisionException: Unable to provision, see the following errors:

1) Error in custom provider, java.lang.IllegalArgumentException: Material name cannot be null

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

public class AWSModule extends AbstractModule {

public AWSModule(String materialSet, String region){
----
}
}

public static void main(String[] args) {
        Injector injector =
                Guice.createInjector(
                        new AWSModule("materialSetValue","regionValue"));
        injector.getInstance(ComprehendHelper.class).detectLanguage("best mobile phone");
    }


Я знаю, что мы можем передать значения через метод configure (), используя

bind.annotatedWith(Names.named("materialSet")).to("materialSetValue");

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

1 Ответ

0 голосов
/ 02 ноября 2019

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

Нет, это не совсем внедрение зависимости. Вы говорите о фабриках здесь:)

Для моего случая использования я не могу жестко закодировать значение набора материалов, поскольку оно всегда будет другим.

В этом случае яне вижу, как @Provides поможет вам, потому что как только вы связываете @Named("materialSet") и @Named("region"), вы не можете их изменить.

Поскольку ваши значения всегда будут разными, я думаю, вам следует использовать Factory для создания ComprehendHelper экземпляров.

@Singleton
class AmazonComprehendFactory {

    public AmazonComprehend create(final String materialSet, final String region) {
        return AmazonComprehendClientBuilder.standard().withCredentials(
                new OdinAWSCredentialsProvider(materialSet))
                .withRegion(region).build();
    }
}

@Singleton
class ComprehendHelperFactory {

    private final AmazonComprehendFactory amazonComprehendFactory;

    @Inject
    ComprehendHelperFactory(AmazonComprehendFactory amazonComprehendFactory) {
        this.amazonComprehendFactory = amazonComprehendFactory;
    }

    public ComprehendHelper create(final String materialSet, final String region) {
        return new ComprehendHelper(amazonComprehendFactory.create(materialSet, region));
    }
}

Если в вашем приложении всегда будет только 1 materialSetи регион, тогда у вас может быть класс для хранения вашей конфигурации и передачи его провайдеру следующим образом.

class AmazonComprehendConfig {

    private final String materialSet;
    private final String region;

    AmazonComprehendConfig(String materialSet, String region) {
        this.materialSet = materialSet;
        this.region = region;
    }

    public String getMaterialSet() {
        return materialSet;
    }

    public String getRegion() {
        return region;
    }
}

public class AWSModule extends AbstractModule {

    @Override
    protected void configure() {
    }

    @Singleton
    @Provides
    AmazonComprehendConfig provideAmazonComprehendConfig() {
        //Load these from properties file or something like that.
        return new AmazonComprehendConfig(materialSet, region);
    }

    @Singleton
    @Provides
    public AmazonComprehend getAWSComprehendClient(AmazonComprehendConfig amazonComprehendConfig) {

        return AmazonComprehendClientBuilder.standard().withCredentials(
                new OdinAWSCredentialsProvider(amazonComprehendConfig.getMaterialSet()))
                .withRegion(amazonComprehendConfig.getRegion()).build();
    }
}

Вы можете избежать использования класса конфигурации, если хотите, и использовать аннотации @Named как-то так.

открытый класс AWSModule расширяет AbstractModule {

    @Override
    protected void configure() {
        bindConstant().annotatedWith(Names.named("materialSet")).to("materialSet");
        bindConstant().annotatedWith(Names.named("region")).to("region");
    }

    @Singleton
    @Provides
    public AmazonComprehend getAWSComprehendClient(@Named("materialSet") final String materialSet,
                                                   @Named("region") final String region) {

        return AmazonComprehendClientBuilder.standard().withCredentials(
                new OdinAWSCredentialsProvider(materialSet))
                .withRegion(region).build();
    }
}
...