“ MembersInjector”和常规“ Method”的注入顺序-注入错误?

时间:2019-01-18 17:27:25

标签: java guice

几天以来,我一直在使用google-guice,并且给我留下了越来越多的印象。

我创建了一个MemberInjector来轻松集成日志记录框架SLF4J,只需添加一个附加注释即可。这意味着不要总是长期使用:

private static final Logger LOG = LoggerFactory.getLogger(MyClass.class);

我现在正在使用:

@Log
Logger LOG;

这真的很棒,但是:
我还在同一个类中使用方法注入作为这种启动函数,并且如果我在那里访问LOG实例,则会导致NPE!因为还没有注入。

@Inject
public void start() { 
    //And here is the problem...
    LOG.info("in start")  //causes NPE, cause LOG is not injected yet
}

如果我在其他(非注入)方法中使用LOG实例,则它可以正常工作。

是否可以更改注入顺序,还是可以告诉guice提前注入MemberInjector?原因我真的很想在方法注入部分中也使用日志记录。

感谢任何提示。

1 个答案:

答案 0 :(得分:0)

我发现的一个解决方案是只创建一个附加的侦听器,以查找已定义的方法(例如“ init”或“ start”),并在创建和注入成员后调用它。

请参阅模块配置:

@Override
protected void configure() {
    bindListener(Matchers.any(), new InitMethodTypeListener());
    //...

InitMethodTypeListener:

public class InitMethodTypeListener implements TypeListener {

    private static final Logger log = LoggerFactory.getLogger(InitMethodTypeListener.class);

    @SuppressWarnings("rawtypes")
    static class InitInvoker implements InjectionListener {
        @Override
        public void afterInjection(final Object injectee) {
            try {
                log.info("Invoke init() from Class: {}", injectee.getClass().getName());
                injectee.getClass().getMethod("init").invoke(injectee);
            } catch (final Exception e) {
                log.error(e.getMessage(), e);
            }
        }

        public static final InitInvoker INSTANCE = new InitInvoker();
    }

    @SuppressWarnings("unchecked")
    @Override
    public <I> void hear(final TypeLiteral<I> type, final TypeEncounter<I> encounter) {

        try {
            if (type.getRawType().getMethod("init") != null) {
                encounter.register(InitInvoker.INSTANCE);
            }
        } catch (final NoSuchMethodException | SecurityException e) {
            // do nothing here, if not init-method found - no call
        }
    }
}

也许这不是直接的方法,但是它可行。因此,我确信在调用init方法时,所有成员都注入良好。

通过此实现,所有受guice控制的对象的“初始化”方法将在对象创建和注入后自动调用。