2014-06-04 16 views
5

Hãy nói rằng tôi có giao diện này:Làm cách nào để chuyển các thông số vào Nhà cung cấp với Guice?

public interface DbMapper{ 
} 

Và sau đó thực hiện điều này:

public interface NameDbMapper extends DbMapper { 

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

thực hiện này tồn tại trong một module, vì vậy tôi không biết tất cả DbMappers tại thời gian biên dịch. Tôi khám phá DbMappers qua phản ánh:

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); 
     } 
    } 

Sau đó, tôi instansiate người vẽ bản đồ trong nhà cung cấp của tôi:

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; 
    } 
} 

tài là một ví dụ @RequestScoped, vì vậy tôi không thể tạo ra các nhà cung cấp thường xuyên trong GuiceModule. Tiêm người dùng làm việc nhưng làm thế nào để vượt qua lớp DBI nên sử dụng thay vì hardcode NameDbMapper trong DbMapperProvider ở đây?

Tôi đã thử phương pháp được đề xuất trong http://google-guice.googlecode.com/git/javadoc/com/google/inject/assistedinject/FactoryModuleBuilder.html nhưng không thể làm cho nó hoạt động.

Mục tiêu ở đây là các mô-đun không cần viết các nhà cung cấp của riêng mình, điều này có thể đạt được không?

Trả lời

7

Bạn có thể liên kết với một trường hợp cung cấp dịch vụ, như

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

Sau đó, thay đổi nhà cung cấp của bạn như thế này:.

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; 
    } 
} 
+0

tôi nhận được "Không thể truy cập đối tượng có phạm vi Hoặc chúng ta không hiện bên trong một Servlet HTTP yêu cầu, hoặc bạn có thể đã quên áp dụng com.google.inject.servlet.GuiceFilter làm bộ lọc servlet cho yêu cầu này. ", Vì lý do nào đó, Guice cố gắng tạo ra các cá thể một cách háo hức trong quá trình khởi tạo? – jontejj

+1

Chắc chắn rồi. Thay vào đó, bạn có thể tiêm Nhà cung cấp . –

+0

Wow! Cảm ơn một bó cho điều này. +1 – jontejj

Các vấn đề liên quan