问题描述
我为我的项目创建了一个模块化系统,该系统使用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 (将#修改为@)