Подтвердить что ты не робот

Использование Google Guice для ввода свойств Java

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

Property1=TEST
Property2=25

пакет com.test;

import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.Properties;

import com.google.inject.AbstractModule;
import com.google.inject.name.Names;

public class TestConfiguration extends AbstractModule {

    @Override
    protected void configure() {
    Properties properties = new Properties();
    try {
        properties.load(new FileReader("Test.properties"));
        Names.bindProperties(binder(), properties);
    } catch (FileNotFoundException e) {
        System.out.println("The configuration file Test.properties can not be found");
    } catch (IOException e) {
        System.out.println("I/O Exception during loading configuration");
    }

    }
}

Я использую основной класс, где я создаю инжектор для ввода свойств.

package com.test;

import com.google.inject.Guice;
import com.google.inject.Injector;

public class Test {

    public static void main(String[] args) {
    TestConfiguration config = new TestConfiguration();
    Injector injector = Guice.createInjector(config);
    TestImpl test = injector.getInstance(TestImpl.class);
    }
}

package com.test;

import com.google.inject.Inject;
import com.google.inject.name.Named;

public class TestImpl {
    private final String property1;
    private final Integer property2;

        @Inject
        public TestImpl(@Named("Property1") String property1, @Named("Property2") Integer property2) {

        System.out.println("Hello World");
        this.property1 = property1;
        this.property2 = property2;

        System.out.println(property1);
        System.out.println(property2);

        }
     }

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

  • Передайте инжектор во все подклассы, а затем используйте инжектор .getInstance(...) для создания подклассов?

  • Включить новый инжектор, например

    TestConfiguration config = new TestConfiguration();
    Injector injector = Guice.createInjector(config);
    TestImpl test = injector.getInstance(TestImpl.class);
    

во всех вложенных классах?

  • Есть ли другой подход, чтобы сделать свойства доступными во всех классах?
4b9b3361

Ответ 1

Передайте инжектор ко всем подклассам, а затем используйте injector.getInstance(...) для создания подклассов?

нет, делая это, вы побеждаете цель шаблона вложения зависимостей и также связываете всю свою реализацию с Guice. Ваши реализации не должны взаимодействовать вообще с guice, кроме как через (теперь стандартизованные) аннотации.

Включить новый инжектор, например

TestConfiguration config = new TestConfiguration(); 
Injector injector = Guice.createInjector(config); 
TestImpl test = injector.getInstance(TestImpl.class); 

во всех вложенных классах?

нет, и это еще хуже, потому что вы закончите с несколькими инжекторами, следовательно, с несколькими контекстами, которые предотвратят правильное использование scopes.

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

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

Свойства могут быть введены так же, как и для TestImpl. Если вы хотите использовать TestImpl, пусть говорят, что служба, которая также нуждается в некоторых свойствах (или других сервисах), просто позвольте Guice вставить ее в TestImpl. Guice заботится обо всех instantiation/wiring. Вы должны только сказать Guice "как действовать", используя связующее, когда Guice не может понять это сам:

public class TestImpl {
    private final String property1;
    private final Integer property2;
    private final IService service;


        @Inject
        public TestImpl(@Named("Property1") String property1, @Named("Property2") Integer property2, IService service) {
           this.property1 = property1;
           this.property2 = property2;
           this.service= service;
        }
    }
}

Ответ 2

Библиотека "Governator" предоставляет функцию сопоставления конфигурации для инъекций guice. Этот подход отличается, но доступен доступ к файлам свойств.

https://github.com/Netflix/governator/wiki/Configuration-Mapping

Ответ 3

Guice-конфигурации


Пример использования: Сначала у нас есть файл свойств 'config.properties':

test.key=test value

И мы хотим ввести это значение следующим образом:

@Inject
@Config( Property.TEST_KEY )
private String injectedValue;

Нам нужно загрузить содержимое файла config.properties в java.util.Properties и передать его в модуль Config:

Properties props = new Properties();
props.load(...);

Модуль configModule = new ConfigModule (props, Property.values()); ... и впрыскивать:

Injector injector = Guice.createInjector( configModule );
TestClass testClass = injector.getInstance( TestClass.class );
String injectedValue = testClass.getInjectedValue();

введенное значение будет "тестовым значением"...

Ответ 4

Библиотека Конфигурация Guice может вставлять вам значения из свойств или файлов JSON в ваши службы.

Вы можете ввести из файла application.properties в свою службу как:

@BindConfig(value = "application", syntax = PROPERTIES)
public class Service {

    @InjectConfig
    private int port;

    @InjectConfig
    private String url;

    @InjectConfig
    private Optional<Integer> timeout;
}

Вы должны просто установить модули ConfigurationModule

public class GuiceModule extends AbstractModule {
    @Override
    protected void configure() {
        install(ConfigurationModule.create());
        requestInjection(Service.class);
    }
}

Ответ 5

"Теперь мой вопрос. Если мой TestImpl создает другие классы, где мне также нужно вводить свойства, и эти классы также должны вводить свойства, что является правильным способом для этого?"

Правило: избегайте использования "нового". Если это абсолютно необходимо, не позволяйте своему классу Impl "создавать другие классы". Вместо этого сообщите свой TestImpl, что при создании с помощью guice он должен получить необходимые экземпляры.