将guice创建的对象注入其他对象

问题描述

我为我的项目创建了一个模块化系统,该系统使用Guice进行依赖项注入。这些模块是抽象Module类的子类,并由Reflections库进行索引。这些模块还注入了Configuration类和Manager类之类的字段。每个模块都可以分配有侦听器,命令或计时器,可以通过注释创建(模块在注释参数中指定)。这些对象也由Reflections索引并随模块一起加载。

我希望能够使用Guice将模块注入到侦听器,命令,计时器或其他模块中,而无需为我创建的每个模块创建绑定。例如:

模块:

public class RandomModule extends Module {

    @Override
    public void onLoad() {
        // Load the module
    }

}

侦听器:

@Listener(module = RandomModule.class) // An annotation for Reflections to index
public class RandomListener extends ListenerAdapter { // ListenerAdapter is a class from a library I am using

    @Inject
    private RandomModule randomModule; // Inject the module somehow

    // Rest of the listener...

}

模块在启动时由ModuleLoader类加载,模块也可以依赖于另一个模块,以确保这些模块先于依赖模块加载。可以使用@Dependencies@Dependency批注来设置依赖关系。

ModuleLoader:

public class ModuleLoader {

    private final Injector injector;

    public ModuleLoader(Manager manager) {
        this.injector = Guice.createInjector(new DefaultModule(manager));
    }

    public void load() {
        // Sorting by dependencies happens here

        for (Class<? extends Module> moduleClass : sortedList) {
            Module module = injector.getInstance(moduleClass);

            logger.info("Loading module {}",moduleClass.getSimpleName());

            modules.put(moduleClass,module);

            // Run timers
            for (Class<?> timerClass : reflections.getTypesAnnotatedWith(Timer.class)) {
                Timer annotation = timerClass.getAnnotation(Timer.class);
                if (annotation.module() != moduleClass || annotation.phase() != ModulePhase.LOAD) continue;

                if (!TimerTask.class.isAssignableFrom(timerClass)) {
                    throw new IllegalStateException("Timer " + timerClass + " has Timer annotation but doesn't extend TimerTask");
                }

                injector.injectMembers(timerClass);
                timer.schedule((TimerTask) injector.getInstance(timerClass),annotation.delay(),annotation.interval());
            }

            injector.injectMembers(moduleClass);

            module.onLoad();
        }
    }

    public void enable(JDA jda) { // JDA is also a class from a library I'm using
        CommandHandler.Builder handlerBuilder = new CommandHandler.Builder();

        for (Class<? extends Module> moduleClass : sortedList) {
            logger.info("Enabling module {}",moduleClass.getSimpleName());

            // Register commands
            for (Class<?> commandClass : reflections.getTypesAnnotatedWith(Command.class)) {
                Command annotation = commandClass.getAnnotation(Command.class);
                if (annotation.module() != moduleClass) continue;

                injector.injectMembers(commandClass);
                handlerBuilder.addCommand(injector.getInstance(commandClass));
            }

            // Register listeners
            for (Class<?> listenerClass : reflections.getTypesAnnotatedWith(Listener.class)) {
                Listener annotation = listenerClass.getAnnotation(Listener.class);
                if (annotation.module() != moduleClass) continue;

                if (!ListenerAdapter.class.isAssignableFrom(listenerClass)) {
                    throw new IllegalStateException("Listener " + listenerClass + " has Listener annotation but doesn't extend ListenerAdapter");
                }

                injector.injectMembers(listenerClass);
                jda.addEventListener(injector.getInstance(listenerClass));
            }

            // Run timers
            for (Class<?> timerClass : reflections.getTypesAnnotatedWith(Timer.class)) {
                Timer annotation = timerClass.getAnnotation(Timer.class);
                if (annotation.module() != moduleClass || annotation.phase() != ModulePhase.ENABLE) continue;

                if (!TimerTask.class.isAssignableFrom(timerClass)) {
                    throw new IllegalStateException("Timer " + timerClass + " has Timer annotation but doesn't extend TimerTask");
                }

                injector.injectMembers(timerClass);
                timer.schedule((TimerTask) injector.getInstance(timerClass),annotation.interval());
            }

            Module module = modules.get(moduleClass);
            module.onEnable();
        }

        this.commandHandler = handlerBuilder.build();
    }

}

我还有一个DefaultModule类,它是一个Guice模块,包含我需要的一些绑定。

DefaultModule:

public class DefaultModule extends AbstractModule {
    private final Manager manager;

    public DefaultModule(Manager manager) {
        this.manager = manager;
    }

    @Override
    protected void configure() {
        bind(JDA.class).toProvider(botManager::getJda).in(Scopes.SINGLETON); // Another class from a library
        bind(Manager.class).toInstance(manager);
        bind(Configuration.class).toProvider(botManager::getConfiguration).in(Scopes.SINGLETON); // A custom configuration class which contains database credentials etc.
        bind(Database.class).toProvider(() -> manager.getModuleLoader().getModule(DatabaseModule.class).getDatabase()).in(Scopes.SINGLETON); // And a database class from a DatabaseModule. This works fine,but I don't want to do this for every single module I create.

        bindListener(Matchers.any(),new Slf4JTypeListener());
    }

}

我是Guice的新手,因此非常感谢您的帮助!请告诉我是否需要更多信息,或者还有其他疑问。

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...