我创建了一个DataSourceProvider来查找容器管理的dataSource:
public class ContainerDataSourceProvider implements Provider<DataSource> {
private final DataSource ds;
@Inject
ContainerDataSourceProvider (String dataSourceName) throws NamingException {
Context initCtx = new InitialContext();
Context envCtx = (Context) initCtx.lookup("java:comp/env");
ds = (DataSource) envCtx.lookup("jdbc/" + dataSourceName);
}
@Override
public DataSource get() {
return ds;
}
}
我不能在提供者上使用@Named注释,因为我希望能够根据dataSourceName提供不同的数据源。
在我的模块中,我想使用提供程序提供多个dataSource绑定。 jdni datasorce的名称来自已绑定到Names的属性文件。
//How do I configure ContainerDataSourceProvider with jndi name "userDataSource"????
binder.bind(DataSource.class).annotatedWith(UserDS.class)
.toProvider(ContainerDataSourceProvider.class);
//How do I configure ContainerDataSourceProvider with jndi name "sessionDataSource"????
binder.bind(DataSource.class).annotatedWith(SessionDS.class)
.toProvider(ContainerDataSourceProvider.class);
然后在我的代码中,我将能够执行类似
的操作public class UserDSClient {
@Inject UserDSClient (@UserDS DataSource ds) {}
}
public class SessionDSClient {
@Inject SessionDSClient (@SessionDS DataSource ds) {}
}
我怎样才能做到这一点?
答案 0 :(得分:1)
这很简单。手动创建提供程序,将数据源名称传递给其构造函数:
public class ContainerDataSourceProvider implements Provider<DataSource> {
private final String dataSourceName;
@Inject
ContainerDataSourceProvider (String dataSourceName) {
this.dataSourceName = dataSourceName;
}
@Override
public DataSource get() {
try {
Context initCtx = new InitialContext();
Context envCtx = (Context) initCtx.lookup("java:comp/env");
return (DataSource) envCtx.lookup("jdbc/" + dataSourceName);
} catch (NamingException e) {
throw new RuntimeException(e);
}
}
}
我还将上下文查找代码移到get()
方法。如果将绑定放在单例范围内,这在性能方面是完全安全的 - 在这种情况下,Guice足够聪明,只能调用provider方法一次。这是绑定:
binder.bind(DataSource.class).annotatedWith(UserDS.class)
.toProvider(new ContainerDataSourceProvider("userDataSource"))
.in(Singleton.class);
binder.bind(DataSource.class).annotatedWith(SessionDS.class)
.toProvider(new ContainerDataSourceProvider("sessionDataSource"))
.in(Singleton.class);
就是这样。
BTW,因为某些原因查找可能会失败,在异常被抛出时,您的代码中的依赖关系解析时间(在Guice.createInjector()
调用或injector.getInstance()
调用中)都会出现异常来自构造函数,以及我的变体。如果您需要处理此错误,请考虑使用throwing providers扩展名。
答案 1 :(得分:0)
我强烈建议您使用Private Modules。私有模块将隐藏环境中的所有绑定信息。因此,您可以在不使用Annotations
的情况下将不同的实现注入同一个接口。
好吧,我做了一个演讲。也许它会帮助你了解私有模块的想法。 http://slid.es/milanbaran/dec