您的位置:首页 > 编程语言 > Java开发

net.paoding.rose —— jade模块源码分析

2017-07-26 00:00 344 查看
使用过rose框架的朋友都知道,rose中dao都是interface类型,那它的实例到底是如何生成的呢?

我们以UserDAO来讲一下到底是如何生成的,并且rose是如何执行sql的

/**
* jade约定了bean的id为jade.dataSource.classPackageName。
* jade约定了这个bean的有效范围为classPackageName所有的DAO。
* jade约定了除非有专门的定义,所有的子目录也受bean上的classpackageName所影响。
* 如果配置文件中没有加载到jade.dataSource的bean,则寻找dataSource bean
**/
public DataSourceHolder getHolder(StatementMetaData metaData,
Map<String, Object> runtimeProperties) {
Class<?> daoClass = metaData.getDAOMetaData().getDAOClass();
DataSourceHolder holder = cachedDataSources.get(daoClass);
if (holder != null) {
return holder;
}

holder = getDataSourceByDirectory(daoClass, daoClass.getName());
if (holder != null) {
cachedDataSources.put(daoClass, holder);
return holder;
}
String catalog = daoClass.getAnnotation(DAO.class).catalog();
if (catalog.length() > 0) {
holder = getDataSourceByDirectory(daoClass, catalog + "." + daoClass.getSimpleName());
}
if (holder != null) {
cachedDataSources.put(daoClass, holder);
return holder;
}
holder = getDataSourceByKey(daoClass, "jade.dataSource");
if (holder != null) {
cachedDataSources.put(daoClass, holder);
return holder;
}
holder = getDataSourceByKey(daoClass, "dataSource");
if (holder != null) {
cachedDataSources.put(daoClass, holder);
return holder;
}
return null;
}

private DataSourceHolder getDataSourceByKey(Class<?> daoClass, String key) {
if (applicationContext.containsBean(key)) {
Object dataSource = applicationContext.getBean(key);
if (!(dataSource instanceof DataSource) && !(dataSource instanceof DataSourceFactory)) {
throw new IllegalClassException("expects DataSource or DataSourceFactory, but a "
+ dataSource.getClass().getName());
}
if (logger.isDebugEnabled()) {
logger.debug("found dataSource: " + key + " for DAO " + daoClass.getName());
}
return new DataSourceHolder(dataSource);
}
return null;
}

一丶生成UserDAO 以下代码为源码中的测试用例

UserDAO dao = getUserDAO();

/**
* 初始调用位置
*/
private UserDAO getUserDAO() {
DataSource dataSource = DataSources.createUniqueDataSource();
JadeFactory factory = new JadeFactory(dataSource);
UserDAO dao = factory.create(UserDAO.class);
dao.createTable();
return dao;
}

创建一个数据源

/**
* 创建一个新的、唯一的DataSource实例,类似xml中配置
* <bean id="dataSource"class="org.springframework.jdbc.datasource.DriverManagerDataSource">
* hsqldb 是一款纯Java编写的数据库 有兴趣的朋友可以一看源码 博客的结尾我会附加源码包
* @return
*/
public static DataSource createUniqueDataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
int random = new Random(Integer.MAX_VALUE).nextInt();
dataSource.setUrl("jdbc:hsqldb:mem:" + System.currentTimeMillis() + "-" + random);
dataSource.setDriverClassName("org.hsqldb.jdbc.JDBCDriver");
return dataSource;
}

至此我们想要的UserDAO的实例就创建好了,jadeFactory对象的create方法

/**
*
*
*/
public <T> T create(Class<?> daoClass) {
try {
//支持DAO类的基础配置(数据源配置、SQL解析器配置、OR映射配置等等)
DAOConfig config = new DAOConfig(dataAccessFactory, rowMapperFactory,
interpreterFactory, cacheProvider, statementWrapperProvider);
//封装缓存一个DAO接口类本身的一些信息,比如类对象、类常量等等
DAOMetaData daoMetaData = new DAOMetaData(daoClass, config);
//DAO代理处理器(一个DAO类对应一个处理器实例)
//JadeInvocationHandler 实现了 InvocationHandler,当我们调用UserDAO中的方法时程序会自动调用
//JadeInvocationHandler中的重写方法invoke(Object proxy, Method method, Object[] args)
JadeInvocationHandler handler = new JadeInvocationHandler(daoMetaData);
ClassLoader classLoader = ClassUtils.getDefaultClassLoader();
return (T) Proxy.newProxyInstance(classLoader, new Class[] { daoClass }, handler);
} catch (RuntimeException e) {
throw new IllegalStateException("failed to create bean for " + daoClass.getName(), e);
}
}

Proxy.newProxyInstance()方法说明

动态代理类(以下简称为代理类)是一个实现在创建类时在运行时指定的接口列表的类,该类具有下面描述的行为。 代理接口 是代理类实现的一个接口。 代理实例 是代理类的一个实例。 每个代理实例都有一个关联的调用处理程序 对象,它可以实现接口 InvocationHandler。通过其中一个代理接口的代理实例上的方法调用将被指派到实例的调用处理程序的 Invoke 方法,并传递代理实例、识别调用方法的 java.lang.reflect.Method 对象以及包含参数的 Object 类型的数组。调用处理程序以适当的方式处理编码的方法调用,并且它返回的结果将作为代理实例上方法调用的结果返回。

二、调用实例中的方法并执行sql

invoke方法

@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
final boolean debugEnabled = logger.isDebugEnabled();
if (debugEnabled) {
logger.debug("invoking " + daoMetaData.getDAOClass().getName() + "#" + method.getName());
}

// 调用object的方法
if (method.getDeclaringClass() == Object.class) {
return invokeObjectMethod(proxy, method, args);
}
// 获取当前DAO方法对应的Statement对象,并记录应使用哪种类型的执行器,
// 将interface类型的UserDAO中执行方法的@SQL注解、@ReturnGeneratedKeys、方法参数
// 是否为批处理等 记录以待查询时使用
Statement statement = getStatement(method);
//
// 将参数放入  Map
Map<String, Object> parameters;
StatementMetaData statemenetMetaData = statement.getMetaData();
if (args == null || args.length == 0) {
parameters = new HashMap<String, Object>(4);
} else {
parameters = new HashMap<String, Object>(args.length * 2 + 4);
for (int i = 0; i < args.length; i++) {
parameters.put(INDEX_NAMES[i], args[i]);
SQLParam sqlParam = statemenetMetaData.getSQLParamAt(i);
if (sqlParam != null) {
parameters.put(sqlParam.value(), args[i]);
}
}
}
// logging
if (debugEnabled) {
logger.info("invoking " + statemenetMetaData);
}

// executing
long begin = System.currentTimeMillis();
//执行sql
final Object result = statement.execute(parameters);
long cost = System.currentTimeMillis() - begin;

// logging
if (sqlLogger.isInfoEnabled()) {
sqlLogger.info(statemenetMetaData + "\tcost " + cost + "ms." );
}
return result;
}

statement的execute方法,判断是否为批处理,然后调用先前statement获得的执行器处理sql

public Object execute(Map<String, Object> parameters) {
Object result;
if (batchUpdate) {
//
Iterable<?> iterable = (Iterable<?>) parameters.get(":1");
Iterator<?> iterator = (Iterator<?>) iterable.iterator();
List<StatementRuntime> runtimes = new LinkedList<StatementRuntime>();
int index = 0;
while (iterator.hasNext()) {
Object arg = iterator.next();
HashMap<String, Object> clone = new HashMap<String, Object>(parameters);
// 更新执行参数
clone.put(":1", arg);
if (metaData.getSQLParamAt(0) != null) {
clone.put(metaData.getSQLParamAt(0).value(), arg);
}
StatementRuntime runtime = new StatementRuntimeImpl(metaData, clone);
for (Interpreter interpreter : interpreters) {
interpreter.interpret(runtime);
}
if (index == 0) {
log(parameters, runtime);
}
runtimes.add(runtime);
index++;
}
result = querier.execute(sqlType, runtimes.toArray(new StatementRuntime[0]));
result = afterInvocationCallback.execute(runtimes.get(0), result);
} else {
StatementRuntime runtime = new StatementRuntimeImpl(metaData, parameters);
for (Interpreter interpreter : interpreters) {
interpreter.interpret(runtime);
}
log(parameters, runtime);
result = querier.execute(sqlType, runtime);
result = afterInvocationCallback.execute(runtime, result);
}
return result;

}

最终调用spring 的 jdbcTemplate执行sql并返回记录

@Override
public <T> List<T> select(String sql, Object[] args, RowMapper<T> rowMapper) {
PreparedStatementCreator csc = getPreparedStatementCreator(sql, args, false);
return jdbcTemplate.query(csc, new RowMapperResultSetExtractor<T>(rowMapper));
}

getPreparedStatementCreator()方法的实现

private PreparedStatementCreator getPreparedStatementCreator(//
final String sql, final Object[] args, final boolean returnKeys) {
PreparedStatementCreator creator = new PreparedStatementCreator() {

@Override
public PreparedStatement createPreparedStatement(Connection con) throws SQLException {
PreparedStatement ps = con.prepareStatement(sql);
if (returnKeys) {
ps = con.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
} else {
ps = con.prepareStatement(sql);
}

if (args != null) {
for (int i = 0; i < args.length; i++) {
Object arg = args[i];
if (arg instanceof SqlParameterValue) {
SqlParameterValue paramValue = (SqlParameterValue) arg;
StatementCreatorUtils.setParameterValue(ps, i + 1, paramValue,
paramValue.getValue());
} else {
StatementCreatorUtils.setParameterValue(ps, i + 1,
SqlTypeValue.TYPE_UNKNOWN, arg);
}
}
}
return ps;
}
};
return creator;
}


hsldb 链接:http://pan.baidu.com/s/1i5Jyd0p 密码:l733
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Paoding-Rose JADE Java