Google Guice: выставить именованный объект, но оставить его доступным в модуле без имени - PullRequest
0 голосов
/ 20 сентября 2018

Мое приложение построено с использованием Guice и MyBatis.Различные подключения к базе данных представлены с использованием javax.sql.DataSource.Все классы, которым требуется доступ к источнику данных, объявляются в том же самом частном модуле Guice, который также предоставляет этот источник данных.Однако эти модули со временем растут и ими сложнее управлять.Кроме того, я хотел бы иметь возможность связать различные DAO и связанные с ними классы в отдельный модуль Guice и снабдить этот модуль источником данных, чтобы вышеупомянутый модуль был лучше инкапсулирован и повторно использован с различными источниками данных.

Технически говоря, я хотел бы иметь возможность написать что-то вроде:

public class MyDataSourceModule extends PrivateModule {

   @Override
   protected void configure() {}

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

, чтобы DataSource все еще был доступен без имени внутри модуля, но только с именем вне модуля.Аннотации могут быть изменены по мере необходимости.Это возможно и как?

1 Ответ

0 голосов
/ 11 февраля 2019

То, что вы хотите, возможно, если создать две разные привязки в одном модуле.

(Примечание: если вы не знакомы с BindingAnnotations, вы можете узнать больше здесь .В моих примерах я буду использовать @UsingSystemDataSource в качестве аннотации привязки.)

Использование EDSL в методе configure():

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 будут выглядеть так:

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

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

Почему это даже работает?

Это фактически создает дваразличные привязки - одна связывает DataSource с SystemDataSource, а другая связывает @UsingSystemDataSource DataSource с DataSource.Используя метод expose() или @Exposed, закрытый модуль предоставляет only аннотированную версию привязки.(Я не смог найти источник, который явно заявляет, что он работает для этого варианта использования, поэтому я протестировал его сам.)

...