Properties の inject

先日のClassToTypeLiteralMatcherAdapter を使用例として
TypeListener 実装で Properties をインジェクトするものを次のように書く
ことができる。

import java.lang.reflect.Field;
import java.util.Enumeration;
import java.util.Properties;
import java.util.ResourceBundle;
import com.google.inject.MembersInjector;
import com.google.inject.TypeLiteral;
import com.google.inject.spi.TypeEncounter;
import com.google.inject.spi.TypeListener;
/**
 * Properties TypeListener
 */

public final class PropertyTypeListner implements TypeListener{
   private Properties prop;
   public PropertyTypeListner(String baseName){
      this.prop = new Properties();
      ResourceBundle bundle = ResourceBundle.getBundle(baseName);
      for(Enumeration<String> en=bundle.getKeys();en.hasMoreElements();){
         String key = en.nextElement();
         this.prop.put(key,bundle.getString(key));
      }
   }
   @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){
                  try{
                  field.set(t,getProperties());
                  }catch(IllegalAccessException e){
                     throw new RuntimeException(e);
                  }
               }
            });

         }
      }
   }
   public Properties getProperties(){
      return this.prop;
   }
}

これを、bindListener で以下のように記述する

Injector injector = Guice.createInjector(new AbstractModule(){
   @Override
   protected void configure(){
      bindListener(new ClassToTypeLiteralMatcherAdapter
(Matchers.subclassesOf(Foo.class))
                  ,
new PropertyTypeListner("foo")
);
   }
});
Foo f = injector.getInstance(FooA.class);
f.exec();

すると、FooA のインジェクトは、
インジェクト対象の Properties がフィールドでもコンストラクタでも良い。
つまり
@Inject private Properties prop

でも良いし、

public class FooA implements Foo{
   private Properties prop;
   @Inject
   public FooA(Properties prop){
      this.prop = prop;
   }

と書いても良い。