Java Guice-基于定义的注入点在运行时将泛型类绑定到实例
我有一个类Java Guice-基于定义的注入点在运行时将泛型类绑定到实例,java,guice,Java,Guice,我有一个类属性,我想在应用程序启动后绑定它Property表示类型为T的属性,其值可以在运行时修改 我有一些可以注入的类: public class MyClass { public MyClass(@Named("someName") Property<String> property) { ... } } 公共类MyClass{ 公共MyClass(@Named(“someName”)属性){ ... } } 我可以绑定这些实例,但只能在应用程序
属性
,我想在应用程序启动后绑定它Property
表示类型为T
的属性,其值可以在运行时修改
我有一些可以注入的类:
public class MyClass {
public MyClass(@Named("someName") Property<String> property) {
...
}
}
公共类MyClass{
公共MyClass(@Named(“someName”)属性){
...
}
}
我可以绑定这些实例,但只能在应用程序启动后绑定,并且我需要知道所有名为的注释值
我已经开始查看
元素
并访问所有元素
实例,以查找其所有绑定
s。一旦有了绑定
,我就可以使用InjectionPoint.forConstructor()
来获取构造函数
困扰我的是,各种类型的绑定都有其不同之处。我必须处理访问LinkedKeyBinding
,UntargetedBinding
,等等。。
对于给定的模块列表,是否有更简单的方法获取所有注入点
?或者我做错了
谢谢 听起来好像您试图为所有foo和bar注入
@Named(foo)属性
,并在事后解决它们,而Guice做得并不特别好。因为Guice配置是在运行时进行的(必须运行configure
方法),所以您可以使用Guice的SPI进行操作的唯一方法是预先绑定所有键,这样Guice就不会抱怨对象图不完整,然后检查它以确定填充什么。这似乎很费劲,而且设计过度
此外,只要Guice允许JIT或“隐式”绑定,在请求对象之前,您就无法知道Guice可能尝试解析的每个键。这可能会使绑定所需的所有内容变得困难,即使您有一个完美的模块或注入器反射库。如果您在创建注入器之前不知道需要什么或有什么可用,那么您也可以绕过Guice的一些依赖关系图验证功能
虽然这不是Guice和依赖注入概念的完美使用,但我会通过编写PropertyOracle
,来调整我的代码:
public class MyClass {
private final Property<String> someNameProperty;
public MyClass(PropertyOracle propertyOracle) {
someNameProperty = propertyOracle.getString("someName");
// The act of getting tells the oracle which properties to get. You can also
// separate those steps without holding onto an instance:
propertyOracle.prepare("keyToBeRequestedLater");
}
}
公共类MyClass{
私有最终财产someNameProperty;
公共MyClass(PropertyOracle PropertyOracle){
someNameProperty=propertyOracle.getString(“someName”);
//获取的行为告诉oracle要获取哪些属性。您还可以
//在不保留实例的情况下分离这些步骤:
房地产触角准备(“keyToBeRequestedLater”);
}
}
尽管这种类型的规定在某种程度上与Guice重复,但与Guice不同,您可以使用任何类型或键插入属性,然后稍后解析它——可能是异步的。然后编写一个假的或模拟的PropertyOracle用于测试,这不像直接注入属性实例那么容易,但是,这可能是在没有Guice SPI复杂性的情况下连接请求的最简单方法。让我们假设注释是声明性的,并且有一个
属性的最终计数。因此,您可以在应用程序启动时扫描它并创建所有绑定
我将创建一个自定义注释,比如说配置带有属性字段(它可以只是值)。
我将为配置注释创建一个类路径扫描程序,并为每个配置注册一个提供程序
然后它看起来像:
你的约束力:
public class MyClass {
public MyClass(@Configuration("someName") Property<String> property) {
...
} }
公共类MyClass{
公共MyClass(@Configuration(“someName”)属性){
...
} }
您的模块:
ClasspathScanner classpathScanner = new ClasspathScanner(
Arrays.asList("com.example"),
Lists.newArrayList());
List<Configuration> configurations = classpathScanner.getClasses().
stream().
filter(c -> find consturctors with Configuration annotation).
collect(Collectors.toList());
configurations.forEach(e -> bind(Key.get(String.class,e)).toProvider(new PropertyStringProvider(e.value())));
ClasspathScanner ClasspathScanner=新的ClasspathScanner(
Arrays.asList(“com.example”),
Lists.newArrayList());
列表配置=classpathScanner.getClasses()。
流()。
过滤器(c->使用配置注释查找constructor)。
collect(Collectors.toList());
configurations.forEach(e->bind(Key.get(String.class,e)).toProvider(newpropertyStringProvider(e.value()));
您的提供商:
public class PropertyStringProvider implements Provider<String> {
private final String propertyName;
public PropertyStringProvider(String propertyName) {
this.propertyName = propertyName;
}
@Override
public String get() {
return //find property for given name. Best to use Archaius framework
}
}
公共类PropertyStringProvider实现提供程序{
私有最终字符串propertyName;
公共PropertyStringProvider(字符串propertyName){
this.propertyName=propertyName;
}
@凌驾
公共字符串get(){
返回//查找给定名称的属性。最好使用Archaius框架
}
}
这是一个基于guice的Governator框架的建议 我最终使用了一个BindingTargetVisitor
,它涵盖了我需要的用例
请注意,此解决方案适用于我们的特定用例,但对于您的用例来说可能过于有限,具体取决于您使用的绑定和注入类型
public class InjectionPointExtractor extends DefaultBindingTargetVisitor<Object, InjectionPoint> {
private final Predicate<TypeLiteral<?>> filter;
public InjectionPointExtractor(Predicate<TypeLiteral<?>> filter) {
this.filter = filter;
}
@Override
public InjectionPoint visit(UntargettedBinding<?> untargettedBinding) {
return getInjectionPointForKey(untargettedBinding.getKey());
}
@Override
public InjectionPoint visit(LinkedKeyBinding<?> linkedKeyBinding) {
return getInjectionPointForKey(linkedKeyBinding.getLinkedKey());
}
@Override
public InjectionPoint visit(ProviderKeyBinding<?> providerKeyBinding) {
return getInjectionPointForKey(providerKeyBinding.getProviderKey());
}
private InjectionPoint getInjectionPointForKey(Key<?> key) {
if (filter.test(key.getTypeLiteral())) {
return InjectionPoint.forConstructorOf(key.getTypeLiteral());
}
return null;
}
}
公共类InjectionPointExtractor扩展了DefaultBindingTargetVisitor{
private final predicate我认为关键在于调用getDependencies()
在每个元素上
您可以,然后为您看到的每个@注释属性
依赖项注册新绑定。我不想使用反射,因为它可能会捕获在Guice中定义但未绑定的类。例如,如果我打开一个库,但只需要它的一些类,我不想要我的应用程序要求我为这个库的所有类定义属性,即使我没有全部使用它们。