Reputation: 103
Assuming such module configure method:
@Override
protected void configure() {
bindListener(Matchers.any(), new TranslationKeyListener());
}
class TranslationKeyListener implements TypeListener {
public <T> void hear(TypeLiteral<T> typeLiteral, TypeEncounter<T> typeEncounter) {
Class<?> clazz = typeLiteral.getRawType();
while (clazz != null) {
for (Field field : clazz.getDeclaredFields()) {
Class<?> fieldType = field.getType();
if (field.isAnnotationPresent(TranslationKey.class) &&
(fieldType == Translation.class)) {
TranslationKey key = field.getAnnotation(TranslationKey.class);
String theKey = key.value();
typeEncounter.register(new TranslationInjector<T>(field, theKey));
}
}
clazz = clazz.getSuperclass();
}
}
}
class TranslationInjector<T> implements MembersInjector<T> {
private final Field field;
private final TranslationImpl translation;
TranslationInjector(Field field, String key) {
this.field = field;
this.translation = new TranslationImpl(key, true);
field.setAccessible(true);
}
@SneakyThrows
public void injectMembers(T t) {
field.set(t, translation);
}
}
and usage in another class like
@TranslationKey("someKey")
private Translation translation; // implemented by TranslationImpl
how can I make sure that dependcies - class fields - using @Inject inside TranslationImpl will be injected as well?
in the same way that requestInjection(this)
works within a module, but this is not supported when called outside configure()...
Upvotes: 1
Views: 182
Reputation: 103
Looks like I found the trick - Guice is rejecting any other attempts to use MembersInjector
if it's not used exactly this way.
The resulting errors of all other attempts has varied from "recursive load", "can't use before Injector is created" and others...
Attempting to call getMembersInjector
before creating TranslationImpl also triggers "recursive load" error for a reason I don't yet understand, but moving it past that makes it work.
class TranslationKeyListener implements TypeListener {
public <T> void hear(TypeLiteral<T> typeLiteral, TypeEncounter<T> typeEncounter) {
Class<?> clazz = typeLiteral.getRawType();
while (clazz != null) {
for (Field field : clazz.getDeclaredFields()) {
Class<?> fieldType = field.getType();
if (field.isAnnotationPresent(TranslationKey.class) &&
(fieldType == Translation.class)) {
TranslationKey key = field.getAnnotation(TranslationKey.class);
String theKey = key.value()
TranslationImpl impl = new TranslationImpl(theKey, true);
MembersInjector injector =
typeEncounter.getMembersInjector(TranslationImpl.class);
typeEncounter.register(new TranslationInjector(field, impl));
typeEncounter.register(new MembersInjector<T>() {
@Override
public void injectMembers(T instance) {
injector.injectMembers(impl);
}
});
}
}
clazz = clazz.getSuperclass();
}
}
}
Upvotes: 1