如何将数据源传递给库?
how to pass a datasource to a library?
我正在编写一个从特定数据模式检索数据的库。这个库包含一个可以是任何东西的数据源对象。现在我已经在我想避免的库中定义了数据源的名称。
import javax.sql.DataSource
public class MyLibraryDao.java {
private static final DS_NAME = "MY_DS_NAME";
@Resource(name = "default", lookup = DS_NAME , type = DataSource.class)
protected DataSource dataSource;
}
DAO class 不直接暴露给客户端。中间有一个服务层:
import javax.inject.Inject;
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.inject.Model;
@ApplicationScoped
@Model
public class MyLibraryService {
@Inject
MyLibraryDao dao;
}
现在,我如何将数据源对象传递给库?
我假设我需要在 DAO 中创建一个带有 DataSource 的构造函数,但是服务呢?
该库将在 CDI 环境中使用。
首先你的库需要一个数据源,让我们声明依赖关系:
public class MyLibraryDao {
@Inject
protected DataSource dataSource;
}
现在使用该库的应用程序的其余部分负责向 CDI 提供数据源;一个简单的方法是:
// Example; your implementation may vary
public class AppDatasourceProducer {
private static final DS_NAME = "MY_APP_DS_NAME";
@Resource(name = "default", lookup = DS_NAME , type = DataSource.class)
protected DataSource dataSource;
@Produces
@ApplicationScoped
public DataSource getDatasource() {
return dataSource;
}
}
有什么变化?现在 您的应用程序 负责了解数据源名称 AND 提供数据源本身。上面的示例可以在支持 @Resource
注释的 JEE 环境中工作。为提供者使用不同的实现可以在例如桌面环境(独立应用程序),使您的库可重用。
确切的数据源名称可能是固定的,就像在示例中一样,或者从配置中读取,例如来自系统属性(如评论中所述);例如:
// Example 2, DS name from system properties
@ApplicationScoped
public class AppDatasourceProducer {
protected DataSource dataSource;
@PostConstruct
void init() throws Exception {
String dsName = System.getProperty("XXXXX");
InitialContext ic = new InitialContext();
dataSource = (DataSource) ic.lookup(dsName);
}
@Produces
@ApplicationScoped
public DataSource getDatasource() {
return dataSource;
}
}
更进一步:
- 无论出于何种原因,使用您的库的应用程序可能正在使用多个数据源。您可能需要提供一个限定符来指定您的应用程序要使用的数据源。
- 为了简单起见,我在
MyLibraryDao
中使用了字段注入。如果您更改为构造函数注入,那么至少 MyLibraryDao
也可以在非 CDI 环境中使用,即如果您以某种方式获得了 DataSource
,您现在可以 new MyLibraryDao(datasource)
。更高的可重用性。
我正在编写一个从特定数据模式检索数据的库。这个库包含一个可以是任何东西的数据源对象。现在我已经在我想避免的库中定义了数据源的名称。
import javax.sql.DataSource
public class MyLibraryDao.java {
private static final DS_NAME = "MY_DS_NAME";
@Resource(name = "default", lookup = DS_NAME , type = DataSource.class)
protected DataSource dataSource;
}
DAO class 不直接暴露给客户端。中间有一个服务层:
import javax.inject.Inject;
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.inject.Model;
@ApplicationScoped
@Model
public class MyLibraryService {
@Inject
MyLibraryDao dao;
}
现在,我如何将数据源对象传递给库?
我假设我需要在 DAO 中创建一个带有 DataSource 的构造函数,但是服务呢? 该库将在 CDI 环境中使用。
首先你的库需要一个数据源,让我们声明依赖关系:
public class MyLibraryDao {
@Inject
protected DataSource dataSource;
}
现在使用该库的应用程序的其余部分负责向 CDI 提供数据源;一个简单的方法是:
// Example; your implementation may vary
public class AppDatasourceProducer {
private static final DS_NAME = "MY_APP_DS_NAME";
@Resource(name = "default", lookup = DS_NAME , type = DataSource.class)
protected DataSource dataSource;
@Produces
@ApplicationScoped
public DataSource getDatasource() {
return dataSource;
}
}
有什么变化?现在 您的应用程序 负责了解数据源名称 AND 提供数据源本身。上面的示例可以在支持 @Resource
注释的 JEE 环境中工作。为提供者使用不同的实现可以在例如桌面环境(独立应用程序),使您的库可重用。
确切的数据源名称可能是固定的,就像在示例中一样,或者从配置中读取,例如来自系统属性(如评论中所述);例如:
// Example 2, DS name from system properties
@ApplicationScoped
public class AppDatasourceProducer {
protected DataSource dataSource;
@PostConstruct
void init() throws Exception {
String dsName = System.getProperty("XXXXX");
InitialContext ic = new InitialContext();
dataSource = (DataSource) ic.lookup(dsName);
}
@Produces
@ApplicationScoped
public DataSource getDatasource() {
return dataSource;
}
}
更进一步:
- 无论出于何种原因,使用您的库的应用程序可能正在使用多个数据源。您可能需要提供一个限定符来指定您的应用程序要使用的数据源。
- 为了简单起见,我在
MyLibraryDao
中使用了字段注入。如果您更改为构造函数注入,那么至少MyLibraryDao
也可以在非 CDI 环境中使用,即如果您以某种方式获得了DataSource
,您现在可以new MyLibraryDao(datasource)
。更高的可重用性。