概述
摘要
当当的Sharding JDBC是在JDBC规范上进行封装来实现数据库分表分库分表功能的。其整体结构非常清晰,主线就是将JDBC规范中的DataSource、Connection、Statement、PreparedStament分别封装为ShardingDataSource、ShardingConnection、ShardingStatement、ShardingPreparedStament类。然后将对象的方法进行重写,而ShardingDataSource、ShardingConnection、ShardingStatement、ShardingPreparedStament类可以看作一个代理对象,它们内部完成了根据逻辑sql语句,转化成真实sql语句,路由找到对应数据源,并根据数据源产生真实的Connection对象,然后执行真实sql语句,并将结果归并返回给应用层的功能。今天来分析一下Sharding JDBC中JdbcMethodInvocation类的作用。
一般情况在调用Connection对象的setAutoCommit方法
try{
con = getConnection();
con.setAutoCommit(false);
/*
* do what you want here.
*/
con.commit();
}catch(Throwable e){
if(con!=null){
try {
con.rollback();
} catch (SQLException e1) {
e1.printStackTrace();
}
}
throw new RuntimeException(e);
}finally{
if(con!=null){
try {
con.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
而ShardingJDBC的ShardingConnection类封装了JDBC中的Connection接口,ShardingConnection只是多个Connection对象的一个代理,直接调用他的重写的setAutoCommit方法无法达到实际的效果,为此ShardingJDBC中引入了JdbcMethodInvocation对ShardingConnection、ShardingStatement、ShardingPreparedStatement类中类似setAutoCommit方法的方法调用进行记录。
JdbcMethodInvocation作用分析
- private final ShardingProperties shardingProperties;
- private final ExecutorEngine executorEngine;
- private final ShardingContext shardingContext;
@Override
public ShardingConnection getConnection() throws SQLException {
MetricsContext.init(shardingProperties);
return new ShardingConnection(shardingContext);
}
得到得到的Connection实际上是包装后的ShardingConnection,而Sharding上下文对象在创建ShardingConnection时被传入。按照上面的一般情况的示例,当我们调用con.setAutoCommit方法时,实际是调用了ShardingDataSource的getConnection方法产生的ShardingConnection对象的setAutoCommit方法。
- private final ShardingContext shardingContext;
- private final Map<String, Connection> connectionMap = new HashMap<>();
public Connection getConnection(final String dataSourceName, final SQLStatementType sqlStatementType) throws SQLException {
Connection result = getConnectionInternal(dataSourceName, sqlStatementType);
replayMethodsInvocation(result);//对记录的要执行的调用方法,在这里通过反射进行执行
return result;
}
private Connection getConnectionInternal(final String dataSourceName, final SQLStatementType sqlStatementType) throws SQLException {
if (connectionMap.containsKey(dataSourceName)) {
return connectionMap.get(dataSourceName);
}
Context metricsContext = MetricsContext.start(Joiner.on("-").join("ShardingConnection-getConnection", dataSourceName));
DataSource dataSource = shardingContext.getShardingRule().getDataSourceRule().getDataSource(dataSourceName);
if (dataSource instanceof MasterSlaveDataSource) {
dataSource = ((MasterSlaveDataSource) dataSource).getDataSource(sqlStatementType);
}
Connection result = dataSource.getConnection();
MetricsContext.stop(metricsContext);
connectionMap.put(dataSourceName, result);//将真实的Connction对象放入connectionMap中
return result;
}
按照上面的一般情况的示例,当我们调用con.setAutoCommit方法时,实际是调用ShardingConnection重写后的setAutoCommit方法。该方法在其父类AbstractConnectionAdapter中完成重写,代码如下:
@Override
public final void setAutoCommit(final boolean autoCommit) throws SQLException {
this.autoCommit = autoCommit;
//getConnections方法实际ShardingConnection对象中的coonectionMap对象的value集合,
//为空时记录调用过的方法与对应参数,当在产生真正的Connection对象时,
//再利用反射的方式让真正的Connection对象调用该方法
if (getConnections().isEmpty()) {
recordMethodInvocation(Connection.class, "setAutoCommit", new Class[] {boolean.class}, new Object[] {autoCommit});
return;
}
for (Connection each : getConnections()) {
each.setAutoCommit(autoCommit);
}
}
public Collection<Connection> getConnections() {
return connectionMap.values();
}
而调用setAutoCommit时coonectionMap还是空。不是达到真实Connection对象的setAutoCommit的目的,为此先对其进行记录,当在产生真实的Connection对象时,再利用反射的方法让其调用recordMethodInvocation方法记录的方法。其中recordMethodInvocation方法继续自WrapperAdapter类。记录了调用的方法与传入方法的参数,实际是将JdbcMethodInvocation对象放入WrapperAdapter的成员变量
private final Collection<JdbcMethodInvocation> jdbcMethodInvocations = new ArrayList<>();
protected final void recordMethodInvocation(final Class<?> targetClass, final String methodName, final Class<?>[] argumentTypes, final Object[] arguments) {
try {
jdbcMethodInvocations.add(new JdbcMethodInvocation(targetClass.getMethod(methodName, argumentTypes), arguments));
} catch (final NoSuchMethodException ex) {
throw new ShardingJdbcException(ex);
}
}
@RequiredArgsConstructor
public final class JdbcMethodInvocation {
private final Method method;//调用的方法
private final Object[] arguments;//调用方法时传入的参数
/**
* 调用方法.
*
* @param target 目标对象
*/
public void invoke(final Object target) {
try {
method.invoke(target, arguments);
} catch (final IllegalAccessException | InvocationTargetException ex) {
throw new ShardingJdbcException("Invoke jdbc method exception", ex);
}
}
}
public Connection getConnection(final String dataSourceName, final SQLStatementType sqlStatementType) throws SQLException {
Connection result = getConnectionInternal(dataSourceName, sqlStatementType);
replayMethodsInvocation(result);//对记录的要执行的调用方法,在这里通过反射进行执行
return result;
}
private Connection getConnectionInternal(final String dataSourceName, final SQLStatementType sqlStatementType) throws SQLException {
if (connectionMap.containsKey(dataSourceName)) {
return connectionMap.get(dataSourceName);
}
Context metricsContext = MetricsContext.start(Joiner.on("-").join("ShardingConnection-getConnection", dataSourceName));
DataSource dataSource = shardingContext.getShardingRule().getDataSourceRule().getDataSource(dataSourceName);
if (dataSource instanceof MasterSlaveDataSource) {
dataSource = ((MasterSlaveDataSource) dataSource).getDataSource(sqlStatementType);
}
Connection result = dataSource.getConnection();
MetricsContext.stop(metricsContext);
connectionMap.put(dataSourceName, result);//将真实的Connction对象放入connectionMap中
return result;
}
protected final void replayMethodsInvocation(final Object target) {
for (JdbcMethodInvocation each : jdbcMethodInvocations) {
each.invoke(target);
}
}
- mmitsetReadOnly
- setTransactionIsolation
- setPoolable
- setFetchSize
- setEscapeProcessing
- setCursorName
- setMaxFieldSize
- setMaxRows
- setQueryTimeout
最后
以上就是傻傻万宝路为你收集整理的Sharding JDBC源码分析-JdbcMethodInvocation类的作用 摘要 一般情况在调用Connection对象的setAutoCommit方法JdbcMethodInvocation作用分析的全部内容,希望文章能够帮你解决Sharding JDBC源码分析-JdbcMethodInvocation类的作用 摘要 一般情况在调用Connection对象的setAutoCommit方法JdbcMethodInvocation作用分析所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复