2016-05-27 35 views
0

我最近一直在使用Google Guice进行黑客入侵,并且我想出了一个想法,根据它在其中声明的类将一个String注入到构造函数中,其他几个参数在注释中定义。例如: 如果我定义了一个新的限定词注释@NamedInjectable由吉斯使用:如何使用Guice注入索引(和类特定)字符串

@Documented 
@Retention(RetentionPolicy.RUNTIME) 
@Target({ ElementType.FIELD, ElementType.PARAMETER }) 
@Qualifier 
public @interface NamedInjectable 
{ 
    String name() default ""; 

    boolean indexed() default true; 
} 

name是一个新的名字基地字符串(默认是只有类的名称),indexed状态是否不是每次注入新字符串都应该增加名称。
例如

public MyClass { 
    @Inject 
    public MyClass(@NamedInjectable(name = "foo", indexed = true) String name) { 
     // some code 
    } 
} 

而且name PARAM应给予一个值,如“ 我认为使用提供商绑定AssistedInject但我可以完成它。一个主要的原因失败,以某种方式获得的名称类。

你有任何其他的想法?

回答

3

有约束力根据名称来定义一个标准的吉斯没有内置的方式。如果你想独自坚守吉斯,你可能需要Custom Injections

除了标准的@ Inject驱动注射,Guice还包括用于自定义注射的钩子。这使得Guice可以托管其他拥有自己的注入语义或注释的框架。大多数开发人员不会直接使用自定义注入;但他们可能会看到他们在扩展和第三方库中的使用。每个自定义注入都需要一个类型监听器,一个注入监听器以及每个注册监听器。

Guice的自定义注射文档示例演示与注射类的类型,这听起来很像是你想定制记录器实例做它没有更多难以阅读您从创建注释的参数在你的TypeListener中。但是,这不会直接与@Inject注释或构造函数一起使用,所以如果您试图使注入完全发生在幕后,可能会遇到麻烦。

另一种选择更简单:只需使用工厂并传入新构建的类。

public MyClass { 
    private final String name; 

    @Inject 
    public MyClass(NameInjector nameInjector) { 
     this.name = nameInjector.get(this, "foo", true); 
    } 
} 
+0

我发现工厂注入更适合我的目的。虽然它看起来像一个矫枉过正的=) –

1

对于普通的Guice注射,您不能访问正在注入东西的类的名称。如果您确实需要这样做,则需要使用自定义注射。

通过使用自定义TypeListener,您可以侦听注射事件并知道正在注射的类。在听到注射事件后,您可以注册Guice将在完成自己的注射后调用的自定义MembersInjector。这个MembersInjector可以访问类的完全构造的实例,所以它可以反映字段并检查注释。但是,它显然不能注入构造函数参数,因为该对象已经被创建。

总之,没有办法自定义注入构造函数参数。但是你描述的想法对于现场注入来说非常可能!

怎么办呢

首先,你需要注册一个TypeListener(基于链接的吉斯wiki页面的代码):

public class NamedStringListener implements TypeListener { 
    public <T> void hear(TypeLiteral<T> typeLiteral, TypeEncounter<T> typeEncounter) { 
     Class<?> clazz = typeLiteral.getRawType(); 
     while (clazz != null) { 
      for (Field field : clazz.getDeclaredFields()) { 
      if (field.getType() == String.class && 
       field.isAnnotationPresent(NamedInjectable.class)) { 
        Annotation annotation = field.getAnnotation(NamedInjectable.class); 

        // How you create and configure this provider is up to you. 
        Provider<String> provider = new MyStringProvider(clazz, annotation); 
        typeEncounter.register(new MyMembersInjector<T>(field, provider)); 
       } 
      } 
     clazz = clazz.getSuperclass(); 
     } 
    } 
} 

然后,里面MyMembersInjector<T>

public class MyMembersInjector<T> implements MembersInjector<T> { 
    final Field field; 
    final Provider<String> provider; 

    NamedMembersInjector(Provider<String> provider) { 
     this.field = field; 
     this.provider = provider; 
     this.field.setAccessible(true); 
    } 

    public void injectMembers(T t) { 
     field.set(t, provider.get()); 
    } 
} 

我离开MyStringProvider的执行由你决定。

查看Guice CustomInjections维基页面了解更多信息。

+0

Thnx。我已经尝试过CustomInjections。据我了解,由于不同的原因,不鼓励现场注入(将“最终”字段留下......) –

相关问题