我目前正在尝试使用Guice在Java控制台应用程序中实现注入。应用程序在数据库中导入XML文件。每个导入操作都在AbstractImporter
中完成,可以是UserImporter
,ScheduleImporter
等。
public class ScheduleMigrator extends AbstractMigrator {
private final UserImporter userImporter;
private final ScheduleImporterFactory scheduleImporterFactory;
@Inject
public ScheduleMigrator(UserImporter userImporter,
ScheduleImporterFactory scheduleImporterFactory) {
this.userImporter = userImporter;
this.scheduleImporterFactory = scheduleImporterFactory;
}
public void migrate() {
// Migrate users
userImporter.run();
// Migrate schedules for each type
for (ScheduleType scheduleTypes : ScheduleType.values()) {
ScheduleImporter importer =
scheduleImporterFactory.create(scheduleTypes);
importer.run();
}
}
}
public class UserImporter extends AbstractImporter {
private final UserTransformer userTransformer;
private final ConfigurationService configurationService;
@Inject
public UserImporter(UserTransformer userTransformer,
ConfigurationService configurationService) {
this.userTransformer = userTransformer;
this.configurationService = configurationService;
}
public void run() {
// do stuff here
}
}
@Singleton
public class UserTransformer {
// ...code ommited...
}
@ImporterScoped
public class ConfigurationService {
// ...code ommited...
}
我已成功为只应在@ImporterScoped
中可用且仅实例化的类创建了我自己的范围(Importer
)。范围是按照the wiki中的步骤创建的。我的问题是,如何在ScheduleMigrator
中输入和退出范围?
正如您在ScheduleMigrator
中看到的那样,每个Importer
都会被注入,并且会调用其run()
方法。还有工厂(基于Guice的@AssistedInject
功能)。这是我希望每个范围开始和结束的地方,UserImporter
和ScheduleImporterFactory
应该在自己的范围内运行。
这是我想要实现的目标的粗略概念:
importerScope.enter();
(new UserImporter()).run();
importerScope.exit();
Guice的文档提到了拦截器的使用,但我对如何实现拦截器感到有点迷失。
答案 0 :(得分:1)
使用AOP似乎是一种非常过度设计的方法,可能会引入问题。我什么时候进入范围?我什么时候退出?如果我实例化两个Importer
对象会发生什么?
相反,我在runScoped
中添加了AbstractMigrator
方法,该方法需要Runnable
并执行它。使用注入我得到ImporterScope
范围,适当地进入和退出。
protected void runScoped(Runnable function)
{
scenarioScope.enter();
try {
function.run();
}
finally {
scenarioScope.exit();
}
}
用法:
runScoped(() -> {
ScheduleImporter importer =
scheduleImporterFactory.create(scheduleTypes);
importer.run();
});
这引入了一个问题。在ScheduleMigrator
中,我不能注入Importers
,因为它们的实例化会在范围之外发生,而Guice会抛出OutOfScopeException
。我必须将每个Importer
包裹在Provider
。
private final Provider<UserImporter> userImporterProvider;
runScoped(() -> {
UserImporter importer = userImporterProvider.get();
importer.run();
});