先日の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;
}
と書いても良い。