ClassToTypeLiteralMatcherAdapter

Google guicebindListener 普遍的な使い方を googlegroup.com で見つけることができた。
インジェクト対象の限定方法として任意のサブクラス(またはimplements)
であることを限定できることだ。

import com.google.inject.TypeLiteral;
import com.google.inject.matcher.AbstractMatcher;
import com.google.inject.matcher.Matcher;
/**
 * ClassToTypeLiteralMatcherAdapter
 */

public class ClassToTypeLiteralMatcherAdapter extends AbstractMatcher<TypeLiteral>{
   private final Matcher<Class> classMatcher;

   public ClassToTypeLiteralMatcherAdapter(Matcher<Class> classMatcher){
       this.classMatcher = classMatcher;
   }

   /*
    * @see com.google.inject.matcher.Matcher#matches(java.lang.Object)
    */

   @Override
   public boolean matches(TypeLiteral typeLiteral){
      return this.classMatcher.matches(typeLiteral.getRawType());
   }
}


この使い方は、TypeListener と伴に使う
bindListener(new ClassToTypeLiteralMatcherAdapter(Matchers.subclassesOf(Foo.class))
,typelistener);


例えば、Foo という interface を実装するクラスに限定して "a"→"AAA" となるProperties を
注入させる場合、
Injector injector = Guice.createInjector で指定する Module に以下の
ような configure を記述する

@Override
protected void configure(){
   bindListener(new ClassToTypeLiteralMatcherAdapter(Matchers.subclassesOf(Foo.class))
,new TypeListener(){
    @Override
    public <T> void hear(TypeLiteral<T> typeLiteral,TypeEncounter<T> typeEncounter){

       for(final Field field : typeLiteral.getRawType().getDeclaredFields()){
           if (field.getType()==Properties.class){
               field.setAccessible(true);
               typeEncounter.register(new MembersInjector<T>(){
                  @Override
                  public void injectMembers(T t){
                     Properties prop = new Properties();
                     prop.setProperty("a","AAA");
                     try{
                     field.set(t,prop);
                     }catch(IllegalAccessException e){
                        throw new RuntimeException(e);
                     }
                  }
               });
             }
          }
       }
   });
}

これは、Wicket の WebApplication の init() 
 addComponentInstantiationListener(new GuiceComponentInjector(Module...));
を書くケースでも効力を発揮できるであろう。