Связывание поставщика гуавы с помощью guice

Я хочу сделать такую ​​привязку,

bind(Supplier<TestClass>).toProvider(Provider<Supplier<TestClass>>).in(Singleton.class);

Поставщик возвращается внешней функцией, поэтому внутри toProvider() я вызываю эту функцию, и она возвращает Provider<Supplier<TestClass>>.

Поставщик из гуавы, причина для этого в том, что есть файл, связанный с TestClass, и мне нужно прочитать этот файл и присвоить эти значения соответствующим полям TestClass.

И этот файл изменяется во время выполнения, поэтому мне нужен способ обновить значения, хранящиеся в TestClass. To-Do этого поставщика гуавы, которого я использовал. У поставщика гуавы есть метод get, и когда этот метод get вызывается, если я использовал memoizeWithExpiration() для создания экземпляра, он проверяет значение TTL, и если оно прошло, то я могу указать лямбда-функцию для чтения файла и присвоения значений.

Так что мне нужно ввести Supplier<TestClass> вот так

@Inject
Supplier<TestClass> someClassSupplier;

Но то, что я делаю эту привязку с Guice, сбивает меня с толку.

Вам действительно следует обновиться до Guice 4 (скоро выйдет Guice 5): Guice 3 действительно устарел, и множество полезных функций для крайних случаев, подобных вашему, присутствуют в 4, которых нет в 3.

Olivier Grégoire 16.12.2020 10:16
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
1
930
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Вы можете использовать следующий тип кода, чтобы делать то, что вы хотите:

class ServiceModule extends AbstractModule {
  private TestClass readTestClassFromFile() {
    return new TestClass();
  }

  // Cache an instance for 5 seconds.
  private final Supplier<TestClass> testClassSupplier = Suppliers.memoizeWithExpiration(this::readTestClassFromFile, 5, SECONDS);

  @Provides TestClass provideTestClass() { // Don't declare as singleton
    return testClassSupplier.get();
  }
}

Затем в вашем классе:

class Service {
  
  @Inject
  Provider<TestClass> testClassProvider; // Inject the provider, not the instance itself, or any supplier.
  
  void doSomething() throws Exception {
    TestClass a = testClassProvider.get();
    TestClass b = testClassProvider.get();

    Thread.sleep(6000); // Sleep for 6 seconds

    TestClass c = testClassProvider.get();

    System.out.println(a == b); // Prints true
    System.out.println(a == c); // Prints false
  }
}

Вы запросили общий способ сделать это, вот он, проверьте метод bindSupplier:

import static com.google.common.base.Suppliers.memoizeWithExpiration;

import com.google.inject.*;
import java.util.concurrent.TimeUnit;
import java.util.function.Supplier;

public class Main {

  public static void main(String[] args) throws Exception {
    Guice.createInjector(new ServiceModule())
        .getInstance(Service.class)
        .doSomething();
  }

  static class ServiceModule extends AbstractModule {
    Dependency createDependency() { return new Dependency(); }

    // For Java 8+
    private <T> void bindSupplier(Class<T> type, Supplier<? extends T> supplier) {
      // Definitely avoid .in(Singleton.class) because you want the scope to be defined by the Supplier.
      bind(type).toProvider(supplier::get);
    }

// For Java 7 and less
//    private <T> void bindSupplier(Class<T> type, final Supplier<? extends T> supplier) {
//      bind(type).toProvider(new Provider<T>() {
//          @Override public T get() { return supplier.get(); }
//        });
//    }

    @Override protected void configure() {
      bindSupplier(Dependency.class,
          memoizeWithExpiration(this::createDependency, 3, TimeUnit.SECONDS));
    }

  }

  static class Dependency {}

  static class Service {

    @Inject Provider<Dependency> dependencyProvider;

    void doSomething() throws InterruptedException {
      Dependency a = dependencyProvider.get();
      Dependency b = dependencyProvider.get();
      Thread.sleep(4000);
      Dependency c = dependencyProvider.get();
      System.out.printf("a == b ? %s%n", a == b); // true
      System.out.printf("a == c ? %s%n", a == c); // false
    }
  }
}

Можем ли мы сделать это универсальным? Я имею в виду, если бы я определил это так, Supplier<T> Это нормально?

Lakith Muthugala 16.12.2020 14:28

@LakithMuthugala Я сделал это максимально общим. Проверьте новый раздел ответа. Если этого недостаточно, то у вас фактически нет вариантов.

Olivier Grégoire 16.12.2020 15:33

Спасибо. @Оливье Грегуар

Lakith Muthugala 16.12.2020 15:57

Другие вопросы по теме