根据请求类类型注入依赖项

时间:2017-04-26 19:53:54

标签: java dependency-injection guice

我有以下情况:

class MyClass implements MyInterface {
    private Logger logger = Logger.getLogger(MyClass.class);

    ... methods ...
}

我认为如果我可以注入我的记录器而不是在类中创建它,那就太好了。

class MyClass implements MyInterface {
    @Inject
    private Logger logger;

    ... methods ...
}

有没有人知道Guice是否可以做这种事情?我一直在使用Guice一段时间,但是无法想出一种基于请求类的类类型注入字段的方法。

1 个答案:

答案 0 :(得分:4)

这不仅可行,而且甚至在自定义注射下的Guice Wiki中有详细描述。有关log4j的完整示例,所有解释都有here。我已经在little projects到slf4j的一个中修改了这个例子,几乎没有任何努力,它运行正常。以下是slf4j的示例:

创建注释:

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface InjectLogger {

}

添加SLF4j类型侦听器:

public class SLF4JTypeListener implements TypeListener {

    public <T> void hear(TypeLiteral<T> typeLiteral,
            TypeEncounter<T> typeEncounter) {

        // the class which members will be injected
        Class<?> clazz = typeLiteral.getRawType();

        while (clazz != null) {
            //add listener for any field
            Arrays.stream(clazz.getDeclaredFields())
                    .filter(this::isLoggerField)
                    .forEach(
                            f -> typeEncounter
                                    .register(new SLF4JMembersInjector<T>(f)));
            clazz = clazz.getSuperclass();
        }
    }

    private boolean isLoggerField(Field f) {
        return f.getType() == Logger.class
                && f.isAnnotationPresent(InjectLogger.class);
    }
}

注射器本身:

public class SLF4JMembersInjector<T> implements MembersInjector<T> {

    private final Field field;
    private final Logger logger;

    SLF4JMembersInjector(Field field) {

        this.field = field;
        this.logger = LoggerFactory.getLogger(field.getDeclaringClass());
        field.setAccessible(true);
    }

    public void injectMembers(T t) {
        try {
            field.set(t, logger);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }
}

最后我的模块中的绑定:

bindListener(Matchers.any(), new SLF4JTypeListener());

用法:

@InjectLogger
private Logger logger;