Google guice の TypeLiteral を使う機会はあまりない。でも Named アノテーションでは
うまくバインド定義を書けない時に便利で利用ルールも限定できる。
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* PropertyBindModule を使用したProperties変数へのインジェクトを約束する。
* propertiesファイルが見つからない場合、空のPropertiesがインジェクトされる。
* PropertyBindModuleコンストラクタ引数有無に関わらず、
* PropertyInject アノテーションでリソースキーを指定すると、
* PropertyInject で指定したリソースキーが優先される
* @Inject @PropertyInject("aaa") private Properties prop;
* → new PropertyBindModule() 実行、new PropertyBindModule("bbb") 実行でも
* aaa.properties を読込もうとする。
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface PropertyInject{
public String value() default "";
}
=======================================================
import java.lang.reflect.Field;
import java.util.MissingResourceException;
import java.util.Properties;
import java.util.ResourceBundle;
import org.apache.log4j.Logger;
import com.google.inject.AbstractModule;
import com.google.inject.MembersInjector;
import com.google.inject.TypeLiteral;
import com.google.inject.matcher.Matchers;
import com.google.inject.spi.TypeEncounter;
import com.google.inject.spi.TypeListener;
public class PropertyBindModule extends AbstractModule{
String resourceKey;
public PropertyBindModule(){}
public PropertyBindModule(String resourceKey){
this.resourceKey = resourceKey;
}
/* (非 Javadoc)
* @see com.google.inject.AbstractModule#configure()
*/
@Override
protected void configure(){
bindListener(Matchers.any()
,new TypeListener(){
@Override
public <T> void hear(TypeLiteral<T> typeLiteral,TypeEncounter<T> typeEncounter){
for(Field field : typeLiteral.getRawType().getDeclaredFields()){
if (field.getType()==Properties.class
&& field.isAnnotationPresent(PropertyInject.class)){
// Properties変数で、@PropertyInject が付いてるもの
typeEncounter.register(new _PropertyInjector<T>(field));
}
}
}
class _PropertyInjector<T> implements MembersInjector<T>{
private final Field field;
_PropertyInjector(Field field){
this.field = field;
this.field.setAccessible(true);
}
@Override
public void injectMembers(T t){
try{
Properties p = new Properties();
String value_PropertyInject
= this.field.getAnnotation(PropertyInject.class).value();
String resourcekey = value_PropertyInject.length()==0
? PropertyBindModule.this.resourceKey
: value_PropertyInject;
if (resourcekey != null && resourcekey.length() > 0){
ResourceBundle rs = ResourceBundle.getBundle(resourcekey);
for(String key : rs.keySet()){
p.setProperty(key,rs.getString(key));
}
}
this.field.set(t,p);
}catch (MissingResourceException e){
Logger.getLogger(this.getClass())
.warn("## MissingResourceException : "+e.getMessage(),e);
}catch(IllegalAccessException e){
throw new RuntimeException(e);
}
}
}
}
);
}
}