Guice可以注入需要查找功能的东西吗?

时间:2014-10-08 23:06:54

标签: java dependency-injection guice

我在Restlet Web服务器中使用Guice,并且有一种我无法弄清楚的模式:如何注入特定用户或特定请求的对象。

假设我们要求列出属于项目的所有小部件。查找Widgets的服务需要Project实例。系统中有许多项目。

我的代码目前看起来像这样:

public class WidgetResource extends ServerResource {

    //path: project/{project}/widgets

    private final WidgetService service;
    private final ProjectLookup projectLookup;

    @Inject
    public WidgetResource(WidgetService service, ProjectLookup projectLookup) {
        this.service = service;
        this.projectLookup = projectLookup;
    }

    @Get
    public WidgetCollection getWidgets() {
        String projectName = getAttribute("project"); //restlet lookup of path var
        Project project = projectLookup.get(projectName);
        WidgetCollection widgets = service.getWidgetsFor(project);
        return widgets;
    }

}

这很好用,但它很笨拙,我希望有更好的方法。直接注入正确的Project对象会很棒。有没有办法做到这一点?

到目前为止,我已经探索了AssistedInject,它提供了一个与我的Lookup非常相似的工厂对象。我接近使用自定义注释/注入的答案,但由于Restlet属性映射直到注入后才填充,因此无法完成。已阅读GitHub文档和用户指南。无法发现任何东西。

我想结束这样的事情:

public class WidgetResource extends ServerResource {

    private final WidgetService service;

    @Inject
    public WidgetResource(WidgetService service) {
        this.service = service;
    }

    @Inject
    @Get
    public WidgetCollection getWidgets(@PathName("project") Project project) {
        WidgetCollection widgets = service.getWidgetsFor(project);
        return widgets;
    }

配置中的(当然)@Provides方法,该方法将查找路径变量并使用查找。但是,我无法想出一种方法将路径名称或Resource实例作为变量提供给提供者方法。这可能吗?任何帮助表示赞赏!

1 个答案:

答案 0 :(得分:0)

您的愿景:您不能注入“getWidgets”...注入会在您创建widgetResource的那一刻发生,所以基本上一旦您的应用程序/服务器启动。

除此之外,它看起来非常好。您有一个REST资源,它接受一个项目参数并使用服务来查找小部件。

如果您事先了解所有可能的项目名称,则可以使用guice'mapBinder代替服务。

public class WidgetsModule extends AbstractModule {
  protected void configure() {
    MapBinder<String, WidgetCollection> mapbinder
        = MapBinder.newMapBinder(binder(), String.class, WidgetCollection.class);
     mapbinder.addBinding("project1").toInstance(...);
     mapbinder.addBinding("project2").toProvider(...);
     mapbinder.addBinding("project3").to(...);
  }
}