我正在研究一个项目并尝试将两个不同的"数据服务"模块组合到一个Web应用程序中(目前,该应用程序是一个桌面Swing应用程序).
每个模块都有自己的Guice(私有)模块.每个Guice模块包含:
@Provides @Inject protected JPQLQuery provideJPQLQuery(EntityManager entityManager) { return new JPAQuery(entityManager); }
稍后将在从db查找内容的类的构造函数中使用它:
@Inject public SomeClassThatLooksObjectsUpFromDatabase(ProviderqueryProvider) { this.queryProvider = queryProvider; }
然后'queryProvider'可以执行查询.
现在,当只安装了一个Guice模块时,这样可以正常工作,但是一旦安装了这两个模块,我(可预见地)会收到此错误:
Unable to create binding for com.mysema.query.jpa.JPQLQuery. It was already configured on one or more child injectors or private modules bound at ServiceOneGuiceModule.provideJPQLQuery() bound at ServiceTwoGuiceModule.provideJPQLQuery()
现在,我理解为什么这个被破坏了 - 我说有两个类型为JPQLQuery的提供者,Guice不知道使用哪一个.
有什么方法可以让Guice将这些提供商分开吗?我想这样做是因为每个模块都有自己正确配置的Hibernate实体,每个实体都有自己独特的数据源(这个项目中有多个数据库).
理想情况下,它会涉及某种方式命名这些提供程序并按名称注入它们(例如我可以单独注入"ServiceOneJPQLQueryProvider"和"ServiceTwoJPQLQueryProvider"),但我还没有找到任何方法来实现这样的任何事情.
(我想一个替代方案是以某种方式配置Hibernate,因此它拥有它需要的所有不同的数据源,然后我可能只需要一个Provider用于我的查询,但这看起来比我上面描述的要多得多)
看看绑定注释,他们习惯于解决你所遇到的问题.
他们建议使用@Named,因为它们是类型安全的,如果拼错它们会产生编译错误而不会产生运行时错误.
简而言之:
ServiceOne.java:
@BindingAnnotation @Target({ FIELD, PARAMETER, METHOD }) @Retention(RUNTIME) public @interface ServiceOne {}
ServiceTwo.java:
@BindingAnnotation @Target({ FIELD, PARAMETER, METHOD }) @Retention(RUNTIME) public @interface ServiceTwo {}
ServiceOneModule.java:
@Provides @ServiceOne @Inject protected JPQLQuery provideJPQLQuery(EntityManager entityManager) { return new JPAQuery(entityManager); }
SomeClass.java:
@Inject public SomeClassThatLooksObjectsUpFromDatabase(@ServiceOne Provider<JPQLQuery> queryProvider) { this.queryProvider = queryProvider; }