java - Java 控制台应用程序中的 Guice 自定义范围进入和退出

标签 java dependency-injection guice interceptor

我目前正在尝试使用 Guice 在 Java 控制台应用程序中实现注入(inject)。该应用程序导入数据库中的 XML 文件。每个导入操作都在 AbstractImporter 中完成,它可以是 UserImporterScheduleImporter 等。

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...

}

我已成功为仅在 Importer 中可用和实例化的类创建了自己的作用域 (@ImporterScoped)。该范围是按照 the wiki 中的步骤创建的。 。我的问题是,我应该如何进入和退出 ScheduleMigrator 中的范围?

正如您在 ScheduleMigrator 中看到的,每个 Importer 都会被注入(inject),并调用其 run() 方法。还有工厂(基于 Guice 的 @AssistedInject 功能)。这是我希望每个作用域开始和结束的地方,UserImporterScheduleImporterFactory 应该在它们自己的作用域中运行。

这是我想要实现的目标的粗略想法:

importerScope.enter();
(new UserImporter()).run();
importerScope.exit();

Guice 的文档提到了拦截器的使用,但我对如何实现它有点迷失。

最佳答案

使用 AOP 似乎是一种过度设计的方法,可能会带来问题。我什么时候进入范围?我什么时候退出?如果我实例化两个 Importer 对象会发生什么?

相反,我在 AbstractMigrator 中添加了一个 runScoped 方法,该方法接受 Runnable 并执行它。使用注入(inject),我获得了 ImporterScope 范围,并适本地进入和退出它。

protected void runScoped(Runnable function)
{
    scenarioScope.enter();

    try {
        function.run();
    }
    finally {
        scenarioScope.exit();
    }
}

用法:

runScoped(() -> {
    ScheduleImporter importer =
            scheduleImporterFactory.create(scheduleTypes);
    importer.run();
});

但这会带来一个问题。在 ScheduleMigrator 中,我无法注入(inject) Importers,因为它们的实例化将发生在范围之外,并且 Guice 会抛出 OutOfScopeException。我必须将每个 Importer 包装在 Provider 中。

private final Provider<UserImporter> userImporterProvider;

runScoped(() -> {
    UserImporter importer = userImporterProvider.get();
    importer.run();
});

关于java - Java 控制台应用程序中的 Guice 自定义范围进入和退出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37775601/

相关文章:

java - 在java库中使用依赖注入(inject)好不好?

java - 关闭 Quartz 调度程序

java - 我有一个日期对象,需要对其进行格式化以进行缓存查找,simpledateformat 不是线程安全的吗?

java - 如何在 eclipse 中为 android ndk c++ 制作 javadoc 样式注释?

php - 如果仍然可以模拟对象,为什么服务定位器不适合测试?

asp.net-mvc - 如何使用 IoC、DI 和 MVC 连接 View 模型上的列表/集合?

java - 扫描仪在使用 next() 或 nextFoo() 后跳过 nextLine()?

java - IntelliJ + JUnit 5(木星)

java - 运行时注入(inject): how do I get the most-childish Injector with Guice?

scala - 播放框架 2.5.x : Inject Environment in a Module