根据 Class 的类型将 Map<String,Object> 注入构造函数
Injecting Map<String,Object> into Constructor based on Type of Class
我有多个 classes,所有这些都需要 Map<String,Object>
注入到它们的构造函数中以提供默认配置,如果需要,用户将覆盖这些默认配置。
@Inject
MyClass(@Nonnull final Map<String,Object> defaults) {}
有很多这些不同的类型,但它们都具有相同的构造函数签名。我知道 @Named()
但我不想管理一堆 String
键的配置,如果有更好的方法来注入基于接收器 class 类型的东西的话。
我需要类似的东西,但找不到类似的东西。
bind(new TypeLiteral<Map<String,Object>>(){}).where(MyClass.class).toInstance(ImmutableMap.<String,Object>of());
如何配置绑定以根据构造函数所属的接收类型 class 将实例绑定到构造函数?
解决方案:
似乎没有办法在不手动添加某种元数据以供 Guice 触发的情况下执行此操作。我想要一些维护开销更少的东西,但这比 @Named
更好,因为它是至少可以在编译时检查的常量。
自定义注释:
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import com.google.inject.BindingAnnotation;
@BindingAnnotation
@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface Defaults { public Class value(); }
将注释参数绑定到实例的模块:
public class DefaultsModule extends AbstractModule
{
private static class Defaults implements com.mycompany.guice.Defaults, Serializable
{
private final Class value;
private Defaults() { this.value = null; }
Defaults(@Nonnull final Class value) { this.value = checkNotNull(value); }
public Class value() { return this.value; }
public int hashCode() { /* This is specified in java.lang.Annotation. */ return (127 * "value".hashCode()) ^ value.hashCode(); }
@Override
public Class<? extends Annotation> annotationType() { return com.mycompany.guice.Defaults.class; }
public boolean equals(Object o)
{
if (!(o instanceof Defaults)) { return false; }
com.mycompany.guice.Defaults other = (com.mycompany.guice.Defaults) o;
return value.equals(other.value());
}
}
@Override
protected void configure()
{
bind(new TypeLiteral<Map<String, Object>>() {}).annotatedWith(new Defaults(MyClassThatNeedsDefaults.class)).toInstance(/* omitted for brevity */);
}
}
用法:
然后你像@Named
一样使用它,但它不依赖于String
!
@Inject
MyClassThatNeedsDefaults(@Nonnull @Defaults(MyClassThatNeedsDefaults.class) final Map<String,Object> defaults) { this.defaults = defaults; }
我有多个 classes,所有这些都需要 Map<String,Object>
注入到它们的构造函数中以提供默认配置,如果需要,用户将覆盖这些默认配置。
@Inject
MyClass(@Nonnull final Map<String,Object> defaults) {}
有很多这些不同的类型,但它们都具有相同的构造函数签名。我知道 @Named()
但我不想管理一堆 String
键的配置,如果有更好的方法来注入基于接收器 class 类型的东西的话。
我需要类似的东西,但找不到类似的东西。
bind(new TypeLiteral<Map<String,Object>>(){}).where(MyClass.class).toInstance(ImmutableMap.<String,Object>of());
如何配置绑定以根据构造函数所属的接收类型 class 将实例绑定到构造函数?
解决方案:
似乎没有办法在不手动添加某种元数据以供 Guice 触发的情况下执行此操作。我想要一些维护开销更少的东西,但这比 @Named
更好,因为它是至少可以在编译时检查的常量。
自定义注释:
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import com.google.inject.BindingAnnotation;
@BindingAnnotation
@Target({ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface Defaults { public Class value(); }
将注释参数绑定到实例的模块:
public class DefaultsModule extends AbstractModule
{
private static class Defaults implements com.mycompany.guice.Defaults, Serializable
{
private final Class value;
private Defaults() { this.value = null; }
Defaults(@Nonnull final Class value) { this.value = checkNotNull(value); }
public Class value() { return this.value; }
public int hashCode() { /* This is specified in java.lang.Annotation. */ return (127 * "value".hashCode()) ^ value.hashCode(); }
@Override
public Class<? extends Annotation> annotationType() { return com.mycompany.guice.Defaults.class; }
public boolean equals(Object o)
{
if (!(o instanceof Defaults)) { return false; }
com.mycompany.guice.Defaults other = (com.mycompany.guice.Defaults) o;
return value.equals(other.value());
}
}
@Override
protected void configure()
{
bind(new TypeLiteral<Map<String, Object>>() {}).annotatedWith(new Defaults(MyClassThatNeedsDefaults.class)).toInstance(/* omitted for brevity */);
}
}
用法:
然后你像@Named
一样使用它,但它不依赖于String
!
@Inject
MyClassThatNeedsDefaults(@Nonnull @Defaults(MyClassThatNeedsDefaults.class) final Map<String,Object> defaults) { this.defaults = defaults; }