使用 guice 绑定番石榴供应商
Binding a guava supplier using guice
我想做这样的绑定,
bind(Supplier<TestClass>).toProvider(Provider<Supplier<TestClass>>).in(Singleton.class);
provider 由外部函数返回,因此,在 toProvider()
内部,我调用了该函数,它 returns Provider<Supplier<TestClass>>
.
供应商来自番石榴,这样做的原因是,有一个与 TestClass 关联的文件,我需要读取该文件并将这些值分配给 TestClass 的各个字段。
并且该文件在 运行 时更改,因此我需要一种方法来刷新存储在 TestClass 中的值。待办事项我使用的番石榴供应商。 Guava 供应商有一个 get 方法,当调用该 get 方法时,如果我使用 memoizeWithExpiration()
创建实例,那么它会检查 TTL 值,如果它通过了,那么我可以指定一个 lambda 函数来读取文件并分配值。
所以我需要像这样注入Supplier<TestClass>
@Inject
Supplier<TestClass> someClassSupplier;
但是与 Guice 的绑定让我感到困惑。
您可以使用以下类型的代码来执行您想要的操作:
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 中:
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
}
}
}
我想做这样的绑定,
bind(Supplier<TestClass>).toProvider(Provider<Supplier<TestClass>>).in(Singleton.class);
provider 由外部函数返回,因此,在 toProvider()
内部,我调用了该函数,它 returns Provider<Supplier<TestClass>>
.
供应商来自番石榴,这样做的原因是,有一个与 TestClass 关联的文件,我需要读取该文件并将这些值分配给 TestClass 的各个字段。
并且该文件在 运行 时更改,因此我需要一种方法来刷新存储在 TestClass 中的值。待办事项我使用的番石榴供应商。 Guava 供应商有一个 get 方法,当调用该 get 方法时,如果我使用 memoizeWithExpiration()
创建实例,那么它会检查 TTL 值,如果它通过了,那么我可以指定一个 lambda 函数来读取文件并分配值。
所以我需要像这样注入Supplier<TestClass>
@Inject
Supplier<TestClass> someClassSupplier;
但是与 Guice 的绑定让我感到困惑。
您可以使用以下类型的代码来执行您想要的操作:
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 中:
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
}
}
}