如何使用Guice将参数传递给Provider?

时间:2014-06-04 06:36:55

标签: java dependency-injection guice

假设我有这个界面:

public interface DbMapper{
}

然后这个实现:

public interface NameDbMapper extends DbMapper {

    @SqlUpdate("insert into names (name) values (:name)")
    void insert(@Bind("name") String name);
}

这个实现存在于一个模块中,所以我不知道编译时的所有DbMappers。我通过反思发现了DbMappers:

public class GuiceModule extends AbstractModule{

    @Override
    protected void configure() {
        Reflections reflections = new Reflections("com.company");
        Set<Class<? extends DbMapper>> dbMappers = reflections.getSubTypesOf(DbMapper.class);

        for (Class<? extends DbMapper> dbMapper : dbMappers) {
            Class<DbMapper> db = (Class<DbMapper>) dbMapper;
            binder().bind(db).toProvider(DbMapperProvider.class);
        }
    }

然后我在我的提供者中实现了映射器:

public class DbMapperProvider implements Provider<DbMapper> {

    private final User user;

    @Inject
    public DbMapperProvider(User user) {
        this.user = user;
    }

    @Override
    public DbMapper get() {
        String jdbc = user.getJdbc();

        DBI userSpecificDatabase = new DBI(jdbc, "user", "password");
        //How to replace NameDbMapper.class here with the db variable in GuiceModule?
        DbMapper dbMapper = userSpecificDatabase.onDemand(NameDbMapper.class);
        return dbMapper;
    }
}

User是@RequestScoped实例,因此我无法在GuiceModule中定期创建提供程序。注入用户但是如何在DbMapperProvider中传递哪个类DBI而不是硬代码NameDbMapper?

我已经尝试了http://google-guice.googlecode.com/git/javadoc/com/google/inject/assistedinject/FactoryModuleBuilder.html中建议的方法,但无法使其发挥作用。

这里的目标是模块不应该编写自己的提供者,这是否可以实现?

1 个答案:

答案 0 :(得分:7)

您可以绑定到提供程序实例,例如

for (Class<? extends DbMapper> dbMapper : dbMappers) {
    bind(dbMapper).toProvider(new DbMapperProvider<>(db));
}

然后像这样修改你的提供者:

public class DbMapperProvider<T extends DbMapper> implements Provider<T> {
    // Use field or method injection
    @Inject
    private Provider<User> user;

    private final Class<T> type;

    public DbMapperProvider(Class<T> type) {
        this.type = type;
    }

    @Override
    public T get() {
        String jdbc = user.get().getJdbc();

        DBI userSpecificDatabase = new DBI(jdbc, "user", "password");
        DbMapper dbMapper = userSpecificDatabase.onDemand(type);
        return dbMapper;
    }
}