如何在使用Provider时将可配置参数传递给构造函数?

时间:2015-03-19 14:27:56

标签: java guice

我最近在Throttler类中添加了Server字段,只有在启用了限制(这是配置条目)时才会实例化,如果是,则每个请求的最大数量sec(另一个配置项)将传递给它的构造函数。

以下是没有依赖注入Throttler的代码:

public class Server {
    private Config config;
    private Throttler throttler;

    @Inject
    public Server(Config config) {
        this.config = config;

        if (config.isThrottlingEnabled()) {
            int maxServerRequestsPerSec = config.getMaxServerRequestsPerSec();
            throttler = new Throttler(maxServerRequestsPerSec);
        }
    }
}

public class Throttler {
    private int maxRequestsPerSec;

    public Throttler(int maxRequestsPerSec) {
        this.maxRequestsPerSec = maxRequestsPerSec
    }
}

现在要注入Throttler,我使用了Provider,因为它并不总是需要实例化。但是现在我被迫将Config注入Throttler并让它自己配置自己":

public class Server {
    private Config config;
    private Provider<Throttler> throttlerProvider;

    @Inject
    public Server(Config config, Provider<Throttler> throttlerProvider) {
        this.config = config;
        this.throttlerProvider = throttlerProvider;

        if (config.isThrottlingEnabled()) {
            this.throttler = throttlerProvider.get();
        }
    }
}

public class Throttler {
    private int maxRequestsPerSec;

    @Inject
    public Throttler(Config config) {
        maxRequestsPerSec = config.getMaxServerRequestsPerSec();
    }
}

我不喜欢这个解决方案,因为:

  1. 实用程序类(Throttler)与Config的依赖关系。
  2. Throttler现在绑定到特定的配置条目,这意味着除Server之外的其他任何内容都不能使用它。
  3. 我更愿意以某种方式将maxRequestsPerSec注入建设者。

    Guice可以吗?

2 个答案:

答案 0 :(得分:2)

Guice FAQ建议引入一个工厂接口,该接口使用其依赖项和客户端传递的其他参数构建类。

public class Throttler {
    ...
    public static class Factory {
        @Inject
        public class Factory(... Throttler dependencies ...) {...}
        public Throttler create(int maxRequestsPerSec) {
            return new Throttler(maxRequestsPerSec /*, injected Throttler dependencies */);
        }
    }
}

这样,Throttler的所有直接依赖关系都保留在Throttler类中。

您还可以使用AssistedInject扩展名来减少样板代码。

答案 1 :(得分:0)

这完全取决于您如何实现Provider接口和应用程序。如果获取maxRequestsPerSec的唯一方法是来自Config,您可以按照以下方式执行操作:

您可以注入特定的Provider实现,并在其中设置一个setter。因此,在构造函数中,您注入CustomProvider<Throttler>(实现Provider),然后执行setMaxRequestsPerSec,然后在实例化Throttler时在get方法中使用它。

如果你不想注射CustomProvider,你可以注入提供者,然后进行instanceof检查,但我认为注入CustomProvider会更好。