Java 控制台应用程序中的 Guice 自定义范围进入和退出
Guice custom scope entry and exit in Java console application
我目前正在尝试使用 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 的文档提到了拦截器的使用,但我对如何实现它有点迷茫。
使用 AOP 似乎是一种过度设计的方法,可能会引入问题。我什么时候进入范围?我什么时候退出?如果我实例化两个 Importer
对象会怎样?
相反,我在 AbstractMigrator
中添加了一个 runScoped
方法,该方法接受 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();
});
我目前正在尝试使用 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 的文档提到了拦截器的使用,但我对如何实现它有点迷茫。
使用 AOP 似乎是一种过度设计的方法,可能会引入问题。我什么时候进入范围?我什么时候退出?如果我实例化两个 Importer
对象会怎样?
相反,我在 AbstractMigrator
中添加了一个 runScoped
方法,该方法接受 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();
});