ShardingSphere源碼解析之執行引擎(三)

上一篇中,我們對ShardingGroupExecuteCallback和SQLExecuteTemplate做了介紹。從設計上講,前者充當ShardingExecuteEngine的回調入口,而後者則是一個模板類,完成對ShardingExecuteEngine的一層封裝並提供了對外的統一入口。這些類都位於底層的sharding-core-execute工程中。從今天開始,我們將進入到sharding-jdbc-core工程,來看看上層設計中的幾個核心類。

根據《ShardingSphere源碼解析之執行引擎(一)》中的整體結構圖,我們可以看到SQLExecuteTemplate的直接使用者是AbstractStatementExecutor類,今天我們就從這個類開始展開討論。該類的變量比較多,我們先來看一下:

    private final DatabaseType databaseType;

    private final int resultSetType;

    private final int resultSetConcurrency;

    private final int resultSetHoldability;

    private final ShardingConnection connection;

    private final SQLExecutePrepareTemplate sqlExecutePrepareTemplate;

    private final SQLExecuteTemplate sqlExecuteTemplate;

    private final Collection<Connection> connections = new LinkedList<>();

    private SQLStatementContext sqlStatementContext;

    private final List<List<Object>> parameterSets = new LinkedList<>();

    private final List<Statement> statements = new LinkedList<>();

    private final List<ResultSet> resultSets = new CopyOnWriteArrayList<>();

    private final Collection<ShardingExecuteGroup<StatementExecuteUnit>> executeGroups = new LinkedList<>();

從這個類開始,我們會慢慢接觸到JDBC相關的對象,因爲ShardingSphere的設計目標是重寫一套與目前的JDBC規範完全兼容的體系。這裏,我們看到的Connection、Statement和ResultSet等對象都是屬於JDBC中的自帶對象,大家都很熟悉。其他的幾個參數如DatabaseType、ShardingConnection等也很重要,對它們的介紹過程中會涉及到sharding-jdbc-core中很多關於數據庫訪問相關的類的介紹,包括我們以前已經接觸過的ShardingStatement和ShardingPreparedStatement等類。我們在具體展開AbstractStatementExecutor類中的實現方法之前需要對這些類有一定的瞭解。

我們先來看一下DatabaseType接口,該接口代表數據庫類型,定義如下:

public interface DatabaseType {  

    String getName();  

    Collection<String> getJdbcUrlPrefixAlias();    

    DataSourceMetaData getDataSourceMetaData(String url, String username);

}

請注意DatabaseType接口位於sharding-core-api包中,而它的實現類位於具體的sharding-core-common包中,其類層結構如下所示:

其中以MySQLDatabaseType爲例,代碼如下所示:

public final class MySQLDatabaseType implements DatabaseType {   

    @Override

    public String getName() {

        return "MySQL";

    }   

    @Override

    public Collection<String> getJdbcUrlPrefixAlias() {

        return Collections.singletonList("jdbc:mysqlx:");

    }   

    @Override

    public MySQLDataSourceMetaData getDataSourceMetaData(final String url, final String username) {

        return new MySQLDataSourceMetaData(url);

    }

}

上述代碼中的MySQLDataSourceMetaData實現了DataSourceMetaData接口,並提供如下所示的對輸入url的解析過程:

    public MySQLDataSourceMetaData(final String url) {

        Matcher matcher = pattern.matcher(url);

        if (!matcher.find()) {

            throw new UnrecognizedDatabaseURLException(url, pattern.pattern());

        }

        hostName = matcher.group(4);

        port = Strings.isNullOrEmpty(matcher.group(5)) ? DEFAULT_PORT : Integer.valueOf(matcher.group(5));

        catalog = matcher.group(6);

        schema = null;

    }

顯然,DatabaseType用於保存與特定數據庫元數據相關的信息。而ShardingSphere還提供了DatabaseTypes類來基於SPI機制實現對各種DatabaseType實例的動態管理,關於SPI機制可以回顧《ShardingSphere源碼解析之微內核架構(下)》中的內容。

然後,我們再來看AbstractStatementExecutor中的ShardingConnection類,這個類非常重要,是對JDBC中Connection的適配和包裝,所以它需要提供Connection接口中的方法,包括createConnection、getMetaData、各種重載的prepareStatement和createStatement以及針對事務的setAutoCommit、commit和rollback方法等,ShardingConnection對這些方法都進行了重寫,如下所示:

這裏面有很多關於事務處理方面的內容,我們後面會有專題進行講解,今天先不做展開。我們先關注ShardingConnection中如下所示的一個上下文對象:

private final ShardingRuntimeContext runtimeContext;   

要講解ShardingRuntimeContext對象,就需要對它的類層結構進行詳細分析。我們發現在sharding-jdbc-core工程中包含了一個RuntimeContext接口,如下所示:

public interface RuntimeContext<T extends BaseRule> extends AutoCloseable {   

    T getRule();   

    ShardingProperties getProps();   

    DatabaseType getDatabaseType();    

    ShardingExecuteEngine getExecuteEngine();    

    SQLParseEngine getParseEngine();

}

可以看到,我們熟悉的SQL解析引擎SQLParseEngine和SQL執行引擎ShardingExecuteEngine都可以通過這個接口進行獲取,也就意味着在這個接口的實現類中應該包含了創建這些引擎的入口。同時,我們還看到了RuntimeContext 應該包含一個BaseRule接口的實現類,而我們前面介紹的ShardingRule和MasterSlaveRule都實現了這個BaseRule接口。

在sharding-jdbc-core工程中,RuntimeContext接口的實現都位於org.apache.shardingsphere.shardingjdbc.jdbc.core.context包中,其類層接口如下所示:

AbstractRuntimeContext這個抽象類實現了RuntimeContext接口,而ShardingRuntimeContext類又擴展了AbstractRuntimeContext,我們先來看AbstractRuntimeContext類。實際上這個類在介紹SQL引擎的第一篇文章《ShardingSphere源碼解析之SQL解析引擎(一)》中已經提到過,讓我們來回顧一下。AbstractRuntimeContext的構造函數中實現了SQLParseEngineFactory和ShardingExecuteEngine的創建,如下所示:

protected AbstractRuntimeContext(final T rule, final Properties props, final DatabaseType databaseType) {

        this.rule = rule;

        this.props = new ShardingProperties(null == props ? new Properties() : props);

        this.databaseType = databaseType;

        executeEngine = new ShardingExecuteEngine(this.props.<Integer>getValue(ShardingPropertiesConstant.EXECUTOR_SIZE));

        parseEngine = SQLParseEngineFactory.getSQLParseEngine(DatabaseTypes.getTrunkDatabaseTypeName(databaseType));

        ConfigurationLogger.log(rule.getRuleConfiguration());

        ConfigurationLogger.log(props);

    }

而在AbstractRuntimeContext的子類ShardingRuntimeContext中,主要工作是創建了與事務相關的ShardingTransactionManagerEngine以及兩個元數據對象DatabaseMetaData和ShardingSphereMetaData。同時這裏還存在一個TableMetaDataInitializer類用於加載表相關的元數據。這些元數據的管理都不屬於核心流程,所以不做詳細展開。

到目前爲止,與ShardingConnection相關的類結構如下圖所示,這是一條類層結構的支線,關注於ShardingConnection內部所包含對象的創建過程:

對於ShardingConnection而言,還有另一條類層結構支線,即作爲一種Connection對象所應該具備的基本結構,我們將在下一篇中對這個話題進行詳細展開。

更多內容可以關注我的公衆號:程序員向架構師轉型。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章