Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Guice dynamic inject with custom annotation

I have some resource, but I can not iterator it and bind them all, I have to use the key to request the resource.So, I have to dynamic inject.

I define an annotation like

@Target({ METHOD, CONSTRUCTOR, FIELD })
@Retention(RUNTIME)
@Documented
@BindingAnnotation
public @interface Res
{
    String value();// the key of the resource
}

use like this

public class Test
{
    @Inject
    @Res("author.name")
    String name;
    @Inject
    @Res("author.age")
    int age;
    @Inject
    @Res("author.blog")
    Uri blog;
}

I have to handle the injection annotated by @Res and I need to know the inject field and the annotation.

Is this possible in Guice and how ? even with spi ?

like image 839
wener Avatar asked Jun 12 '14 04:06

wener


1 Answers

I work out follow CustomInjections

Code like this

public class PropsModule extends AbstractModule
{
    private final Props props;
    private final InProps inProps;

    private PropsModule(Props props)
    {
        this.props = props;
        this.inProps = InProps.in(props);
    }

    public static PropsModule of(Props props)
    {
        return new PropsModule(props);
    }

    @Override
    protected void configure()
    {
        bindListener(Matchers.any(), new TypeListener()
        {
            @Override
            public <I> void hear(TypeLiteral<I> type, TypeEncounter<I> encounter)
            {
                Class<? super I> clazz = type.getRawType();
                if (!clazz.isAnnotationPresent(WithProp.class))
                    return;
                for (Field field : clazz.getDeclaredFields())
                {
                    Prop prop = field.getAnnotation(Prop.class);
                    if (prop == null)
                        continue;

                    encounter.register(new PropInjector<I>(prop, field));
                }
            }
        });
    }

    class PropInjector<T> implements MembersInjector<T>
    {
        private final Prop prop;
        private final Field field;

        PropInjector(Prop prop, Field field)
        {
            this.prop = prop;
            this.field = field;
            field.setAccessible(true);
        }

        @Override
        public void injectMembers(T instance)
        {
            try {
                Class<?> targetType = field.getType();
                Object val = inProps.as(prop.value(), targetType);
                field.set(instance, val);
            } catch (IllegalAccessException e) {
                throw new RuntimeException(e);
            }
        }
    }
}
like image 173
wener Avatar answered Oct 18 '22 15:10

wener