05 How Is the Configuration System in Sharding Sphere Designed

05 How is the Configuration System in ShardingSphere Designed #

In the previous lesson, we discussed several approaches to apply ShardingSphere in business systems. We found that besides mastering the functionalities of common frameworks like Spring, Spring Boot, and MyBatis, the main task of using ShardingSphere is to configure various sharding-related settings according to business requirements. Today, I will guide you to analyze how the configuration system in ShardingSphere is designed and implemented, as this is a prerequisite for us to introduce the core functionalities of ShardingSphere.

What is row expression? #

Before we delve into the configuration system, let’s first introduce a utility function provided by the ShardingSphere framework for developers, which is the row expression.

Row expression is a tool used in ShardingSphere to simplify and unify configuration information, and it is widely used in daily development. Its usage is quite straightforward, just use the \({expression} or \)->{expression} expression in the configuration.

For example, “ds\({0..1}.user\){0..1}” used in the previous lesson is a row expression used to set the available data sources or data table names. Based on the row expression syntax, \({begin..end} represents a range from “begin” to “end”, and multiple \){expression} can be connected by “.” to represent a Cartesian product relationship among multiple expression values. In graphical form, the “ds\({0..1}.user\){0..1}” expression will be resolved into the following result:

image

Of course, similar scenarios can also use enumerations to enumerate all possible values. Row expression also provides the syntax \({[enum1, enum2,…, enumx]} to represent enumerated values. Therefore, the effect of “ds\){0..1}.user\({0..1}” is equivalent to “ds\){[0,1]}.user${[0,1]}”.

Similarly, the expression ds${age % 2} used in the previous lesson represents choosing the target data source as ds0 or ds1 based on the modulus operation of the age field. Therefore, besides configuring data source and data table names, another common application of row expression in ShardingSphere is to configure various sharding algorithms, which we will see a lot in the subsequent examples.

Since \({expression} conflicts with Spring’s own property file placeholders, and Spring is currently the mainstream development framework, it is recommended to use \)->{expression} for configuration in production environments.

What are the core configurations in ShardingSphere? #

For operations like database sharding, table sharding, and read-write splitting, the main task of configuration is to create and initialize various rules. Configuration is the core of the entire ShardingSphere framework, and it is our main task in daily development. It can be said that once we master the core configuration items of ShardingSphere, we have essentially mastered how to use this framework. So, what are the core configurations in ShardingSphere? Here, we will take the sharding engine as an example to introduce several commonly used configuration items, while the configuration items related to read-write splitting, data desensitization, and orchestration governance will be explained in detail in specific application scenarios.

ShardingRuleConfiguration #

In the previous lesson, we have learned how to create a DataSource through integration between frameworks. This DataSource is the entry point for using ShardingSphere. We also saw that during the process of creating the DataSource, a ShardingDataSourceFactory class is used, and this factory class requires a ShardingRuleConfiguration object to be passed in its constructor. Obviously, from the naming perspective, this ShardingRuleConfiguration is the entry point for configuring sharding rules.

ShardingRuleConfiguration has multiple configuration items, and we can explain them simply with a diagram. In this diagram, we list the names, types, and relationship of each configuration item:

image

Here, we introduce some new concepts like binding table and broadcast table, which will be explained in detail when we introduce database sharding and table sharding in the next lesson, so we won’t go into detail here. In fact, for ShardingRuleConfiguration, there is only one required configuration item, which is TableRuleConfiguration.

TableRuleConfiguration #

From the name, TableRuleConfiguration is the configuration for table sharding rules, but in fact, it includes settings for both database sharding and table sharding. TableRuleConfiguration includes many important configuration items:

  • actualDataNodes

actualDataNodes represents the actual data nodes, composed of the data source name and table name, and supports row expressions. For example, the “ds\({0..1}.user\){0..1}” mentioned before is a typical configuration.

  • databaseShardingStrategyConfig

databaseShardingStrategyConfig represents the database sharding strategy, and if not set, the default database sharding strategy defined in ShardingRuleConfiguration will be used.

  • tableShardingStrategyConfig Like databaseShardingStrategyConfig, tableShardingStrategyConfig represents the sharding strategy for tables. If not set, the default sharding strategy will be used, which is defined in the defaultTableShardingStrategyConfig configuration in ShardingRuleConfiguration.
  • keyGeneratorConfig

keyGeneratorConfig represents the configuration for the auto-increment column in a distributed environment. ShardingSphere integrates various distributed ID generators, such as Snowflake algorithm, for generating distributed IDs.

ShardingStrategyConfiguration #

We notice that both databaseShardingStrategyConfig and tableShardingStrategyConfig are of the type ShardingStrategyConfiguration. In ShardingSphere, ShardingStrategyConfiguration is actually an empty interface with a series of implementation classes, each representing a sharding strategy:

3.png Class hierarchy of ShardingStrategyConfiguration

In these concrete sharding strategies, it usually requires specifying a sharding column shardingColumn and one or more sharding algorithms ShardingAlgorithm. However, there are exceptions, for example, HintShardingStrategyConfiguration directly uses the database’s hint mechanism for forced routing, so it does not require a sharding column. We will analyze the implementation process of these strategies in detail in “Routing Engine: How to Integrate Multiple Sharding Strategies and Sharding Algorithms in the Routing Process?”.

KeyGeneratorConfiguration #

For an auto-increment column, KeyGeneratorConfiguration needs to specify a column name column first. Also, because ShardingSphere provides a set of built-in mechanisms for generating auto-increment columns (such as Snowflake algorithm SNOWFLAKE and universally unique identifier UUID), it needs to be specified by the type configuration item. Finally, we can use the Properties configuration item to specify the relevant property configurations required for the generation of the auto-increment value. We have also seen an example of this in the previous lesson, where the workerId is configured as 33 in the Snowflake algorithm.

With the above core configurations, we can already perform common operations of sharding databases and tables in daily development. Of course, different developers may have different preferences on how to integrate these configuration information into their business code using a specific method. Therefore, ShardingSphere also provides a series of configuration methods for developers to choose from.

What configuration methods does ShardingSphere provide? #

From Java code to configuration files, ShardingSphere provides 4 configuration methods for different usage scenarios:

  • Java code configuration
  • Yaml configuration
  • Spring namespace configuration
  • Spring Boot configuration

Let’s take a look at these four specific methods.

Java Code Configuration #

Java code configuration is the original way to use the underlying API provided by ShardingSphere to complete the configuration system construction. In the previous lesson, we have already seen how to initialize the ShardingRuleConfiguration and TableRuleConfiguration classes, and create the target DataSource through ShardingDataSourceFactory. We won’t go into details here.

In daily development, we generally do not directly use Java code to configure the ShardingSphere configuration system. On the one hand, if Java code is used to implement the configuration, once there are changes, the code needs to be recompiled and published, which is not conducive to the dynamic management of configuration information and continuous integration of the system. On the other hand, the code-level configuration method is also relatively cumbersome, not direct and prone to errors, and has poor maintainability.

Of course, there may also be exceptions. One situation is that if we need to integrate or customize development at a more underlying level with other frameworks, often only Java code can achieve the desired effect. At the same time, for developers who have just started using ShardingSphere, developing based on the API provided by the framework is more conducive to quickly mastering the relationship between various classes and class hierarchies provided by the framework.

Yaml Configuration #

Yaml configuration is a configuration method advocated by ShardingSphere. Yaml syntax is similar to other high-level languages, and it can intuitively describe data formats such as multi-level lists and objects, making it particularly suitable for representing or editing data structures and various configuration files.

In terms of syntax, the common “!!” indicates the instantiation of the class; multiple lines starting with “-” form an array; “:” indicates a key-value pair; and “#” indicates a comment. For more information about Yaml syntax, you can refer to Baidu Baike https://baike.baidu.com/item/YAML. Please note that Yaml is case-sensitive and uses indentation to indicate the hierarchical relationship. Here is an example of a configuration for implementing read-write separation with ShardingSphere:

dataSources:
  dsmaster: !!com.alibaba.druid.pool.DruidDataSource
    driverClassName: com.mysql.jdbc.Driver

(The rest of the content exceeds the assistant’s maximum response length. #

    spring.shardingsphere.datasource.dsslave1.username=root
    spring.shardingsphere.datasource.dsslave1.password=root
    
    spring.shardingsphere.masterslave.name=health_ms
    spring.shardingsphere.masterslave.master-data-source-name=dsmaster
    spring.shardingsphere.masterslave.slave-data-source-names=dsslave0, dsslave1

As we can see, three DataSources - dsmaster, dsslave0, and dsslave1 are configured with their respective driver information. Finally, a masterSlaveRule rule is configured based on these three DataSources to specify the master-slave architecture.

In ShardingSphere, configuration information can be stored in a .yaml configuration file, and the configuration information can be parsed by loading this configuration file. This mechanism provides more flexibility and customizability for developers to efficiently manage configuration information. In the last part of today’s content, we will delve into the implementation principles of this mechanism in detail.

Spring Namespace Configuration #

We can use a custom configuration tag to extend the Spring namespace, embedding various custom configuration items in Spring. Starting from version 2.0, the Spring framework provides an extension mechanism for defining Javabeans based on XML Schema. By defining XML Schema, the configuration forms that used to be defined by complex Javabean compositions can be presented in a simpler and more readable way. An XML based on Schema consists of three parts, and we use an example to illustrate:

<master-slave:load-balance-algorithm id="randomStrategy"/>

In this XML, master-slave is the namespace, which can clearly distinguish the logical category it belongs to, which is used to implement read-write separation. load-balance-algorithm is an element representing the load balancing algorithm in read-write separation. The ID is a configuration option in load balancing, and its value is the random strategy randomStrategy.

In ShardingSphere, we can also use namespaces to achieve full read-write separation configuration:

<beans
    ...
    http://shardingsphere.apache.org/schema/shardingsphere/masterslave
    http://shardingsphere.apache.org/schema/shardingsphere/masterslave/master-slave.xsd"> 
    <bean id=" dsmaster " class=" com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/dsmaster"/>
        <property name="username" value="root"/>
        <property name="password" value="root"/>
    </bean>

    <bean id="dsslave0" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/dsslave0"/>
        <property name="username" value="root"/>
        <property name="password" value="root"/>
    </bean>

    <bean id="dsslave1" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="jdbc:mysql://localhost:3306/dsslave1"/>
        <property name="username" value="root"/>
        <property name="password" value="root"/>
    </bean> 
    <master-slave:load-balance-algorithm id="randomStrategy" type="RANDOM" />
    <master-slave:data-source id="masterSlaveDataSource" master-data-source-name="dsmaster" slave-data-source-names="dsslave0, dsslave1" strategy-ref="randomStrategy" />
</beans>

In this code, we introduce the new namespace master-slave in Spring and set the load balancing algorithm and the three master-slave DataSources.

Spring Boot Configuration #

Spring Boot has become the most popular development framework in the Java field. It provides a design concept of convention over configuration. Typically, developers can place configuration items in the application.properties file. At the same time, in order to facilitate the management and maintenance of configuration information, Spring Boot also provides the concept of profiles, which can flexibly organize configuration information for different environments or application scenarios. When using profiles, there is a naming convention for configuration files:

{application}-{profile}.properties

Based on this naming convention, if we want to name based on whether the target is a traditional single-database single-table scenario or a master-slave architecture read-write separation scenario, we need to provide two different .properties configuration files, as shown in the following code:

application-traditional.properties application-master-slave.properties

In these two file names, traditional and master-slave are the specific profiles. Now we can use the spring.profiles.active configuration item in the application.properties file to set the current profile:

#spring.profiles.active=traditional spring.profiles.active=master-slave

Spring Boot’s configuration style is a set of key-value pairs, and we can also use this style to implement the read-write separation configuration introduced earlier:

spring.shardingsphere.datasource.names=dsmaster,dsslave0,dsslave1 
spring.shardingsphere.datasource.dsmaster.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.dsmaster.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.dsmaster.url=jdbc:mysql://localhost:3306/dsmaster
spring.shardingsphere.datasource.dsmaster.username=root
spring.shardingsphere.datasource.dsmaster.password=root 
spring.shardingsphere.datasource.dsslave0.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.dsslave0.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.dsslave0.url=jdbc:mysql://localhost:3306/dsslave0
spring.shardingsphere.datasource.dsslave0.username=root
spring.shardingsphere.datasource.dsslave0.password=root 
spring.shardingsphere.datasource.dsslave1.type=com.alibaba.druid.pool.DruidDataSource
spring.shardingsphere.datasource.dsslave1.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.dsslave1.url=jdbc:mysql://localhost:3306/dsslave1
spring.shardingsphere.datasource.dsslave1.username=root
spring.shardingsphere.datasource.dsslave1.password=root 
spring.shardingsphere.masterslave.load-balance-algorithm-type=random
spring.shardingsphere.masterslave.name=health_ms
spring.shardingsphere.masterslave.master-data-source-name=dsmaster
spring.shardingsphere.masterslave.slave-data-source-names=dsslave0,dsslave1

With these different configuration options, developers can flexibly complete the configuration work based on their own expertise or the requirements of the development framework. In the subsequent content of this course, we will combine the use of Yaml configuration and Spring Boot configuration to introduce the specific usage of ShardingSphere.

How does the configuration system of ShardingSphere work? #

Although rarely used in daily development, among the four configuration methods introduced earlier, the Java code configuration implementation is the easiest to understand. We can organize the configuration functionality provided by ShardingSphere by examining the calling relationships between the configuration classes. Therefore, in order to have a deep understanding of the implementation principles of the configuration system, let’s start with the ShardingRuleConfiguration class.

ShardingRuleConfiguration Configuration System #

For ShardingSphere, the role of the configuration system is essentially to initialize JDBC objects such as DataSource. For example, ShardingDataSourceFactory creates a ShardingDataSource object based on the passed-in data source Map, ShardingRuleConfiguration, and Properties:

public final class ShardingDataSourceFactory {

    public static DataSource createDataSource(
            final Map<String, DataSource> dataSourceMap, final ShardingRuleConfiguration shardingRuleConfig, final Properties props) throws SQLException {
        return new ShardingDataSource(dataSourceMap, new ShardingRule(shardingRuleConfig, dataSourceMap.keySet()), props);
    } 
}

In ShardingSphere, all rule configuration classes implement a top-level interface called RuleConfiguration. RuleConfiguration is an empty interface, and ShardingRuleConfiguration is one of the implementation classes of this interface, specifically used for processing the application scenarios of the sharding engine. The following code shows the implementation process of the ShardingRuleConfiguration class:

public final class ShardingRuleConfiguration implements RuleConfiguration {
    // Table sharding rule list
    private Collection<TableRuleConfiguration> tableRuleConfigs = new LinkedList<>();
    // Binding table rule list
    private Collection<String> bindingTableGroups = new LinkedList<>();
    // Broadcast table rule list
    private Collection<String> broadcastTables = new LinkedList<>();
    // Default data source
    private String defaultDataSourceName;
    // Default database sharding strategy
    private ShardingStrategyConfiguration defaultDatabaseShardingStrategyConfig;
    // Default table sharding strategy
    private ShardingStrategyConfiguration defaultTableShardingStrategyConfig;
    // Default key generator for auto-incrementing columns
    private KeyGeneratorConfiguration defaultKeyGeneratorConfig;
    // Master-slave rule
    private Collection<MasterSlaveRuleConfiguration> masterSlaveRuleConfigs = new LinkedList<>();
    // Data encryption rule
    private EncryptRuleConfiguration encryptRuleConfig;
}

As can be seen, ShardingRuleConfiguration contains a series of configuration class definitions. Based on the introduction in the previous content, we have understood the roles and usage methods of these configuration classes. Among them, the core TableRuleConfiguration definition is also relatively simple, mainly including the definition of the logical table, actual data nodes, database sharding strategy, and table sharding strategy:

public final class TableRuleConfiguration {
    // Logical table
    private final String logicTable;
    // Actual data nodes
    private final String actualDataNodes;
    // Database sharding strategy
    private ShardingStrategyConfiguration databaseShardingStrategyConfig;
    // Table sharding strategy
    private ShardingStrategyConfiguration tableShardingStrategyConfig;
    // Key generator for auto-incrementing columns
    private KeyGeneratorConfiguration keyGeneratorConfig;

    public TableRuleConfiguration(final String logicTable) {
        this(logicTable, null);
    }

    public TableRuleConfiguration(final String logicTable, final String actualDataNodes) {
        Preconditions.checkArgument(!Strings.isNullOrEmpty(logicTable), "LogicTable is required.");
        this.logicTable = logicTable;
        this.actualDataNodes = actualDataNodes;
    }
}

Due to limited space, we will not go into detail about the definitions of other configuration classes. In fact, regardless of the configuration method used, all configuration items are encapsulated and converted based on these core configuration classes. The usage methods based on Spring namespace and Spring Boot configuration are more common. The implementation principles of these two methods rely on the integration of ShardingSphere with these two frameworks. I will provide detailed explanations in the following lessons. Yaml configuration is a highly recommended usage method by ShardingSphere. Therefore, ShardingSphere has a special handling for Yaml configuration internally. Today, we will analyze in detail the complete implementation solution for Yaml configuration.

YamlShardingRuleConfiguration Configuration System #

In the sharding-core-common project of the ShardingSphere source code, there is a package structure called org.apache.shardingsphere.core.yaml.config, which contains all the implementation classes related to Yaml configuration.

Just like RuleConfiguration, ShardingSphere also provides an empty YamlConfiguration interface. There are many implementation classes of this interface, but we find that there is a unique abstract class YamlRootRuleConfiguration, which obviously is the base class in the Yaml configuration system. In this YamlRootRuleConfiguration, it contains the data source Map and Properties:

public abstract class YamlRootRuleConfiguration implements YamlConfiguration {

    private Map<String, DataSource> dataSources = new HashMap<>();

    private Properties props = new Properties();
}

In the above code, we find that the corresponding class of ShardingRuleConfiguration is missing. In fact, the definition of this class is in the YamlRootRuleConfiguration’s subclass YamlRootShardingConfiguration, and its class name YamlShardingRuleConfiguration is simply to add the prefix Yaml to ShardingRuleConfiguration, as shown in the following code:

public class YamlRootShardingConfiguration extends YamlRootRuleConfiguration {

    private YamlShardingRuleConfiguration shardingRule;
}

Next, we come to the YamlShardingRuleConfiguration class and find that the variables it contains correspond one-to-one with the variables in the ShardingRuleConfiguration class. These Yaml configuration classes are all located in the org.apache.shardingsphere.core.yaml.config.sharding package:

public class YamlShardingRuleConfiguration implements YamlConfiguration {

    private Map<String, YamlTableRuleConfiguration> tables = new LinkedHashMap<>();
    private Collection<String> bindingTables = new ArrayList<>();
    private Collection<String> broadcastTables = new ArrayList<>();
    private String defaultDataSourceName;
    private YamlShardingStrategyConfiguration defaultDatabaseStrategy;
    private YamlShardingStrategyConfiguration defaultTableStrategy;
    private YamlKeyGeneratorConfiguration defaultKeyGenerator;
    private Map<String, YamlMasterSlaveRuleConfiguration> masterSlaveRules = new LinkedHashMap<>();
    private YamlEncryptRuleConfiguration encryptRule;
}

So how is this YamlShardingRuleConfiguration constructed? This will take us to the YamlShardingDataSourceFactory factory class, which is actually a further encapsulation of the ShardingDataSourceFactory class. The following code demonstrates this process:

public final class YamlShardingDataSourceFactory {

    public static DataSource createDataSource(final File yamlFile) throws SQLException, IOException {
        YamlRootShardingConfiguration config = YamlEngine.unmarshal(yamlFile, YamlRootShardingConfiguration.class);
        return ShardingDataSourceFactory.createDataSource(config.getDataSources(), new ShardingRuleConfigurationYamlSwapper().swap(config.getShardingRule()), config.getProps());
    }
    // ...
}

We can see that the input parameter of the createDataSource method is a File object. We use this File object to construct a YamlRootShardingConfiguration object, and then obtain a ShardingRuleConfiguration object from the YamlRootShardingConfiguration object, which is then passed to ShardingDataSourceFactory to complete the construction of the target DataSource. The call relationship here is a bit complex, so let’s clarify the class structure of the entire process, as shown in the following diagram:

image

Obviously, two new utility classes are introduced here, YamlEngine and YamlSwapper. Let’s see what role they play in the whole process.

YamlEngine and YamlSwapper #

The role of YamlEngine is to convert various forms of input content into a Yaml object, including File, string, byte[] and so on. YamlEngine contains a batch of unmarshal/marshal methods to complete the conversion of data. Taking File input as an example, the unmarshal method completes the construction of the Yaml object by loading FileInputStream:

public static <T extends YamlConfiguration> T unmarshal(final File yamlFile, final Class<T> classType) throws IOException {
    try (
        FileInputStream fileInputStream = new FileInputStream(yamlFile);
        InputStreamReader inputStreamReader = new InputStreamReader(fileInputStream, "UTF-8")
    ) {
        return new Yaml(new Constructor(classType)).loadAs(inputStreamReader, classType);
    }
}

When classType, the desired type, is passed into the unmarshal method, we can obtain an instance of the class corresponding to this classType. In YamlShardingDataSourceFactory, we pass in the YamlRootShardingConfiguration type, so we will obtain an instance of the class YamlShardingRuleConfiguration for YamlRootShardingConfiguration.

After obtaining YamlShardingRuleConfiguration, the next step is to convert it to ShardingRuleConfiguration. In order to complete this one-to-one conversion between classes with corresponding relationships, ShardingSphere also provides a set of converter classes, and ShardingRuleConfigurationYamlSwapper is one of them. ShardingRuleConfigurationYamlSwapper implements the YamlSwapper interface:

public interface YamlSwapper<Y extends YamlConfiguration, T> {
    Y swap(T data);
    T swap(Y yamlConfiguration);
}

It can be seen that a pair of methods are provided here to complete the mutual conversion between the two data structures. In ShardingRuleConfigurationYamlSwapper, the code structure of the swap method that takes the target object as ShardingRuleConfiguration is basically a one-to-one conversion of the corresponding fields between YamlShardingRuleConfiguration and ShardingRuleConfiguration:

@Override
public ShardingRuleConfiguration swap(final YamlShardingRuleConfiguration yamlConfiguration) {
    ShardingRuleConfiguration result = new ShardingRuleConfiguration();
    for (Entry<String, YamlTableRuleConfiguration> entry : yamlConfiguration.getTables().entrySet()) {
        YamlTableRuleConfiguration tableRuleConfig = entry.getValue();
        tableRuleConfig.setLogicTable(entry.getKey());
        result.getTableRuleConfigs().add(tableRuleConfigurationYamlSwapper.swap(tableRuleConfig));
    }
    result.setDefaultDataSourceName(yamlConfiguration.getDefaultDataSourceName());
    result.getBindingTableGroups().addAll(yamlConfiguration.getBindingTables());
    result.getBroadcastTables().addAll(yamlConfiguration.getBroadcastTables());
    if (null != yamlConfiguration.getDefaultDatabaseStrategy()) {
        result.setDefaultDatabaseShardingStrategyConfig(shardingStrategyConfigurationYamlSwapper.swap(yamlConfiguration.getDefaultDatabaseStrategy()));
    }
    if (null != yamlConfiguration.getDefaultTableStrategy()) {
        result.setDefaultTableShardingStrategyConfig(shardingStrategyConfigurationYamlSwapper.swap(yamlConfiguration.getDefaultTableStrategy()));
    }
    if (null != yamlConfiguration.getDefaultKeyGenerator()) {
        result.setDefaultKeyGeneratorConfig(keyGeneratorConfigurationYamlSwapper.swap(yamlConfiguration.getDefaultKeyGenerator()));
    }
    Collection<MasterSlaveRuleConfiguration> masterSlaveRuleConfigs = new LinkedList<>();
    for (Entry<String, YamlMasterSlaveRuleConfiguration> entry : yamlConfiguration.getMasterSlaveRules().entrySet()) {
        YamlMasterSlaveRuleConfiguration each = entry.getValue();
        each.setName(entry.getKey());
        masterSlaveRuleConfigs.add(masterSlaveRuleConfigurationYamlSwapper.swap(entry.getValue()));
    }
    result.setMasterSlaveRuleConfigs(masterSlaveRuleConfigs);
    if (null != yamlConfiguration.getEncryptRule()) {
        result.setEncryptRuleConfig(encryptRuleConfigurationYamlSwapper.swap(yamlConfiguration.getEncryptRule()));
    }
    return result;
}

This way, we obtain a ShardingRuleConfiguration object from the external Yaml file, and then can use the ShardingDataSourceFactory factory class to complete the creation process of the target DataSource.

Summary #

Continuing from the previous lesson, in this lesson we have provided a comprehensive introduction to the configuration system in ShardingSphere. In fact, when using this framework, configuration is the main task for developers. We have outlined the core configuration items in ShardingSphere, and then provided four specific configuration methods, which are Java code configuration, Yaml configuration, Spring namespace configuration, and Spring Boot configuration. Finally, from the perspective of implementation principles, we have analyzed in depth the specific Yaml configuration method.

Here is a question for you to think about: What is the relationship between the core classes related to the configuration system in ShardingSphere?

Starting from the next lesson, we will use the configuration system provided by ShardingSphere to gradually complete the development work of sharding, read/write splitting and sharding + read/write splitting.