GoogleGuice:公开一个命名对象,但在没有名称的模块中保持它可用

GoogleGuice:公开一个命名对象,但在没有名称的模块中保持它可用,guice,Guice,我的应用程序是使用Guice和MyBatis构建的。 使用javax.sql.DataSource表示不同的数据库连接。 所有需要访问数据源的类都在提供该数据源的同一Guice PrivateModule中声明。 但是,这些模块会随着时间的推移而增长,并且更难管理。此外,我希望能够将不同的DAO及其相关类绑定到一个单独的Guice模块中,并为该模块提供一个数据源,以便更好地封装上述模块,并可在不同的数据源中重用 从技术上讲,我希望能够写出如下内容: public class MyDataSour

我的应用程序是使用Guice和MyBatis构建的。 使用javax.sql.DataSource表示不同的数据库连接。 所有需要访问数据源的类都在提供该数据源的同一Guice PrivateModule中声明。 但是,这些模块会随着时间的推移而增长,并且更难管理。此外,我希望能够将不同的DAO及其相关类绑定到一个单独的Guice模块中,并为该模块提供一个数据源,以便更好地封装上述模块,并可在不同的数据源中重用

从技术上讲,我希望能够写出如下内容:

public class MyDataSourceModule extends PrivateModule {

   @Override
   protected void configure() {}

   @Exposed
   @Named("systemDataSource")
   @Singleton
   @Provides
   DataSource provideDataSource() {
       return ...;
   }
}

这样,数据源在模块内没有名称但仅在模块外有名称时仍然可用。注释可以根据需要进行更改。这是可能的吗?如何实现?

通过在同一模块中创建两个不同的绑定,可以实现您想要的

(旁注:如果您不熟悉BindingAnnotation,您可以了解更多。在我的示例中,我将使用
@UsingSystemDataSource
作为绑定注释。)

configure()
方法中使用EDSL:

protected void configure() {
    // binding for private use
    bind(DataSource.class).to(SystemDataSourceImpl.class).in(Scopes.SINGLETON);

    // binding for public use
    bind(DataSource.class).annotatedWith(@UsingSystemDataSource.class).to(DataSource.class);
    expose(DataSource.class).annotatedWith(@UsingSystemDataSource.class);
}
现在,如果您需要在不使用EDSL的情况下执行此操作,那么您的私有模块
@提供的方法将如下所示:

@Provides
@Exposed
@UsingSystemDataSource
DataSource provideDataSourcePublicly(DataSource privatelyBoundDatasource) {
    return privatelyBoundDatasource;
}

@Provides
@Singleton
DataSource provideDataSource() {
    return ...;
}

为什么这样做有效?


这实际上创建了两个不同的绑定,一个链接到
DataSource
SystemDataSource
,另一个链接到
@UsingSystemDataSource-DataSource
DataSource
。使用
expose()
方法或
@Exposed
,专用模块仅公开带注释的绑定版本。(我找不到明确说明它适用于此用例的源代码,所以我自己测试了它。)

您是否尝试过自己的代码示例?乍一看,我看不出它有什么不起作用的原因。您是否尝试过我的代码示例,或者只是看了一眼?:-)一旦你@命名了某个东西,就很难只按类型而不按名称访问它。不,我还没有机会运行它。您是否有一些约束要求您使用
@Provides
方法,或者您是否可以使用使用EDSL绑定的解决方案?这很好,但为什么您要创建@UsingSystemDataSource BindingAnnotations而不是使用@Named?这是一种“最佳实践”。Guice建议使用专门构建的注释,因为编译器可以检查它们。(编译器无法查看
@Named
中的字符串是否正确。)好的,但是运行时在启动时会非常快。我喜欢命名的概念和它内置的事实。但这并没有改变答案多少。