搭建个人网站教程,赣州网站建设哪家便宜,wordpress 流量,离线推广网站规划书Sharding JDBC自动配置的原理
与所有starter一样#xff0c;shardingsphere-jdbc-core-spring-boot-starter也是通过SPI自动配置的原理实现分库分表配置加载#xff0c;spring.factories文件中的自动配置类shardingsphere-jdbc-core-spring-boot-starter功不可没#xff0c…Sharding JDBC自动配置的原理
与所有starter一样shardingsphere-jdbc-core-spring-boot-starter也是通过SPI自动配置的原理实现分库分表配置加载spring.factories文件中的自动配置类shardingsphere-jdbc-core-spring-boot-starter功不可没他主要是自动创建了模式bean、事务类型bean和数据源bean配置加载的过程可以归纳如下 #mermaid-svg-CRcQ7ODjQS7bHtwt {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-CRcQ7ODjQS7bHtwt .error-icon{fill:#552222;}#mermaid-svg-CRcQ7ODjQS7bHtwt .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-CRcQ7ODjQS7bHtwt .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-CRcQ7ODjQS7bHtwt .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-CRcQ7ODjQS7bHtwt .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-CRcQ7ODjQS7bHtwt .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-CRcQ7ODjQS7bHtwt .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-CRcQ7ODjQS7bHtwt .marker{fill:#333333;stroke:#333333;}#mermaid-svg-CRcQ7ODjQS7bHtwt .marker.cross{stroke:#333333;}#mermaid-svg-CRcQ7ODjQS7bHtwt svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-CRcQ7ODjQS7bHtwt .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-CRcQ7ODjQS7bHtwt .cluster-label text{fill:#333;}#mermaid-svg-CRcQ7ODjQS7bHtwt .cluster-label span{color:#333;}#mermaid-svg-CRcQ7ODjQS7bHtwt .label text,#mermaid-svg-CRcQ7ODjQS7bHtwt span{fill:#333;color:#333;}#mermaid-svg-CRcQ7ODjQS7bHtwt .node rect,#mermaid-svg-CRcQ7ODjQS7bHtwt .node circle,#mermaid-svg-CRcQ7ODjQS7bHtwt .node ellipse,#mermaid-svg-CRcQ7ODjQS7bHtwt .node polygon,#mermaid-svg-CRcQ7ODjQS7bHtwt .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-CRcQ7ODjQS7bHtwt .node .label{text-align:center;}#mermaid-svg-CRcQ7ODjQS7bHtwt .node.clickable{cursor:pointer;}#mermaid-svg-CRcQ7ODjQS7bHtwt .arrowheadPath{fill:#333333;}#mermaid-svg-CRcQ7ODjQS7bHtwt .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-CRcQ7ODjQS7bHtwt .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-CRcQ7ODjQS7bHtwt .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-CRcQ7ODjQS7bHtwt .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-CRcQ7ODjQS7bHtwt .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-CRcQ7ODjQS7bHtwt .cluster text{fill:#333;}#mermaid-svg-CRcQ7ODjQS7bHtwt .cluster span{color:#333;}#mermaid-svg-CRcQ7ODjQS7bHtwt div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-CRcQ7ODjQS7bHtwt :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 创建模式bean 创建数据源bean 创建事务类型扫描bean ShardingSphereAutoConfiguration ModeConfiguration ShardingSphereDataSource TransactionTypeScanner 其中创建数据源bean时会根据不同的模式创建不同的bean本地模式直接从配置文件中加载配置中心模式就从配置中心加载。ShardingSphereAutoConfiguration的实现如下
Configuration
ComponentScan(org.apache.shardingsphere.spring.boot.converter)
EnableConfigurationProperties(SpringBootPropertiesConfiguration.class)
AutoConfigureBefore(DataSourceAutoConfiguration.class)
RequiredArgsConstructor
public class ShardingSphereAutoConfiguration implements EnvironmentAware {private String databaseName;private final SpringBootPropertiesConfiguration props;private final MapString, DataSource dataSourceMap new LinkedHashMap();/*** 模式配置** return mode configuration*/Beanpublic ModeConfiguration modeConfiguration() {return null props.getMode() ? null : new YamlModeConfigurationSwapper().swapToObject(props.getMode());}/*** 单机模式从本地配置中加载DataSource** param rules rules configuration* param modeConfig mode configuration* return data source bean* throws SQLException SQL exception*/BeanConditional(LocalRulesCondition.class)Autowired(required false)public DataSource shardingSphereDataSource(final ObjectProviderListRuleConfiguration rules, final ObjectProviderModeConfiguration modeConfig) throws SQLException {CollectionRuleConfiguration ruleConfigs Optional.ofNullable(rules.getIfAvailable()).orElseGet(Collections::emptyList);return ShardingSphereDataSourceFactory.createDataSource(databaseName, modeConfig.getIfAvailable(), dataSourceMap, ruleConfigs, props.getProps());}/*** 集群模式从配置中心中加载DataSource** param modeConfig mode configuration* return data source bean* throws SQLException SQL exception*/BeanConditionalOnMissingBean(DataSource.class)public DataSource dataSource(final ModeConfiguration modeConfig) throws SQLException {return !dataSourceMap.isEmpty() ? ShardingSphereDataSourceFactory.createDataSource(databaseName, modeConfig, dataSourceMap, Collections.emptyList(), props.getProps()): ShardingSphereDataSourceFactory.createDataSource(databaseName, modeConfig);}/*** 事务类型扫描bean** return transaction type scanner*/Beanpublic TransactionTypeScanner transactionTypeScanner() {return new TransactionTypeScanner();}Overridepublic final void setEnvironment(final Environment environment) {dataSourceMap.putAll(DataSourceMapSetter.getDataSourceMap(environment));databaseName DatabaseNameSetter.getDatabaseName(environment);}
}下面以单机模式出发点理一下加载的过程。
Bean
Conditional(LocalRulesCondition.class)
Autowired(required false)
public DataSource shardingSphereDataSource(final ObjectProviderListRuleConfiguration rules, final ObjectProviderModeConfiguration modeConfig) throws SQLException {CollectionRuleConfiguration ruleConfigs Optional.ofNullable(rules.getIfAvailable()).orElseGet(Collections::emptyList);// 通过ShardingSphereDataSourceFactory工厂创建数据源return ShardingSphereDataSourceFactory.createDataSource(databaseName, modeConfig.getIfAvailable(), dataSourceMap, ruleConfigs, props.getProps());
}通过对源码的跟踪可以发现ShardingSphereDataSourceFactory.createDataSource创建数据源经历了如下的过程 #mermaid-svg-AQbyFbXnvcCzw2xV {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-AQbyFbXnvcCzw2xV .error-icon{fill:#552222;}#mermaid-svg-AQbyFbXnvcCzw2xV .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-AQbyFbXnvcCzw2xV .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-AQbyFbXnvcCzw2xV .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-AQbyFbXnvcCzw2xV .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-AQbyFbXnvcCzw2xV .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-AQbyFbXnvcCzw2xV .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-AQbyFbXnvcCzw2xV .marker{fill:#333333;stroke:#333333;}#mermaid-svg-AQbyFbXnvcCzw2xV .marker.cross{stroke:#333333;}#mermaid-svg-AQbyFbXnvcCzw2xV svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-AQbyFbXnvcCzw2xV .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-AQbyFbXnvcCzw2xV .cluster-label text{fill:#333;}#mermaid-svg-AQbyFbXnvcCzw2xV .cluster-label span{color:#333;}#mermaid-svg-AQbyFbXnvcCzw2xV .label text,#mermaid-svg-AQbyFbXnvcCzw2xV span{fill:#333;color:#333;}#mermaid-svg-AQbyFbXnvcCzw2xV .node rect,#mermaid-svg-AQbyFbXnvcCzw2xV .node circle,#mermaid-svg-AQbyFbXnvcCzw2xV .node ellipse,#mermaid-svg-AQbyFbXnvcCzw2xV .node polygon,#mermaid-svg-AQbyFbXnvcCzw2xV .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-AQbyFbXnvcCzw2xV .node .label{text-align:center;}#mermaid-svg-AQbyFbXnvcCzw2xV .node.clickable{cursor:pointer;}#mermaid-svg-AQbyFbXnvcCzw2xV .arrowheadPath{fill:#333333;}#mermaid-svg-AQbyFbXnvcCzw2xV .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-AQbyFbXnvcCzw2xV .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-AQbyFbXnvcCzw2xV .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-AQbyFbXnvcCzw2xV .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-AQbyFbXnvcCzw2xV .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-AQbyFbXnvcCzw2xV .cluster text{fill:#333;}#mermaid-svg-AQbyFbXnvcCzw2xV .cluster span{color:#333;}#mermaid-svg-AQbyFbXnvcCzw2xV div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-AQbyFbXnvcCzw2xV :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 创建数据源bean new 创建上下文管理器 创建JDBC上下文 创建InstanceMetaData 根据mode调用 创建元数据上下文 创建数据库连接元数据 调用 加载分片规则 new ShardingSphereAutoConfiguration ShardingSphereDataSourceFactory.createDataSource ShardingSphereDataSource ShardingSphereDataSource.createContextManager JDBCContext InstanceMetaDataBuilderFactory.create StandaloneContextManagerBuilder.build MetaDataContextsFactory.create ShardingSphereDatabasesFactory.create ShardingSphereDatabase.create DatabaseRulesBuilder.build ShardingSphereDatabase 分片规则加载原理
分片规则、审计规则、key生成规则都是通过SPI的方式加载自动配置类ShardingSphereAutoConfiguration中创建ShardingSphereDataSource的时候会加载配置的分片规则创建核心配置类ShardingRule在ShardingRule的创建中会通过SPI的方式加载分片规则。加载的过程如下 #mermaid-svg-zFpHfQ5UZ0lnfi1U {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-zFpHfQ5UZ0lnfi1U .error-icon{fill:#552222;}#mermaid-svg-zFpHfQ5UZ0lnfi1U .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-zFpHfQ5UZ0lnfi1U .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-zFpHfQ5UZ0lnfi1U .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-zFpHfQ5UZ0lnfi1U .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-zFpHfQ5UZ0lnfi1U .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-zFpHfQ5UZ0lnfi1U .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-zFpHfQ5UZ0lnfi1U .marker{fill:#333333;stroke:#333333;}#mermaid-svg-zFpHfQ5UZ0lnfi1U .marker.cross{stroke:#333333;}#mermaid-svg-zFpHfQ5UZ0lnfi1U svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-zFpHfQ5UZ0lnfi1U .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-zFpHfQ5UZ0lnfi1U .cluster-label text{fill:#333;}#mermaid-svg-zFpHfQ5UZ0lnfi1U .cluster-label span{color:#333;}#mermaid-svg-zFpHfQ5UZ0lnfi1U .label text,#mermaid-svg-zFpHfQ5UZ0lnfi1U span{fill:#333;color:#333;}#mermaid-svg-zFpHfQ5UZ0lnfi1U .node rect,#mermaid-svg-zFpHfQ5UZ0lnfi1U .node circle,#mermaid-svg-zFpHfQ5UZ0lnfi1U .node ellipse,#mermaid-svg-zFpHfQ5UZ0lnfi1U .node polygon,#mermaid-svg-zFpHfQ5UZ0lnfi1U .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-zFpHfQ5UZ0lnfi1U .node .label{text-align:center;}#mermaid-svg-zFpHfQ5UZ0lnfi1U .node.clickable{cursor:pointer;}#mermaid-svg-zFpHfQ5UZ0lnfi1U .arrowheadPath{fill:#333333;}#mermaid-svg-zFpHfQ5UZ0lnfi1U .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-zFpHfQ5UZ0lnfi1U .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-zFpHfQ5UZ0lnfi1U .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-zFpHfQ5UZ0lnfi1U .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-zFpHfQ5UZ0lnfi1U .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-zFpHfQ5UZ0lnfi1U .cluster text{fill:#333;}#mermaid-svg-zFpHfQ5UZ0lnfi1U .cluster span{color:#333;}#mermaid-svg-zFpHfQ5UZ0lnfi1U div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-zFpHfQ5UZ0lnfi1U :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 创建数据源bean 查询实例 通过SPI Class获取服务实例 Y:创建新的service实例 N:Map中获取service单例 创建分片规则 创建分片规则 创建核心分库分表规则 分片规则 Key生成规则 审计规则 通过工厂创建分片算法 获取注册的service SPI方式获取service 通过工厂创建key生成算法 通过工厂创建审计算法 ShardingSphereAutoConfiguration ShardingSphereDataSource 一系列加载... DatabaseRulesBuilder.build OrderedSPIRegistry.getRegisteredServices ShardingSphereServiceLoader.getServiceInstances(spiClass) 带SingletonSPI注解? service.getClass().getDeclaredConstructor().newInstance() SERVICES.getOrDefault(serviceInterface, Collections.emptyList()) ShardingRuleBuilder.build new ShardingRule ShardingAlgorithmFactory.newInstance KeyGenerateAlgorithmFactory.newInstance ShardingAuditAlgorithmFactory.newInstance ShardingSphereAlgorithmFactory.createAlgorithm TypedSPIRegistry.getRegisteredService ShardingSphereServiceLoader.getServiceInstances(spiClass) SPI核心实现类ShardingSphereServiceLoader中会将SPI接口进行Map缓存管理需要时直接获取。如果Map中不存在就通过反射的方式新建服务实例具体实现源码如下
public final class ShardingSphereServiceLoader {// 缓存service实例// 缓存的Key,如// org.apache.shardingsphere.sharding.spi.ShardingAlgorithm// org.apache.shardingsphere.sharding.spi.KeyGenerateAlgorithm// org.apache.shardingsphere.transaction.spi.ShardingSphereTransactionManagerprivate static final MapClass?, CollectionObject SERVICES new ConcurrentHashMap();/*** 注册服务实例** param 服务接口*/public static void register(final Class? serviceInterface) {if (!SERVICES.containsKey(serviceInterface)) {SERVICES.put(serviceInterface, load(serviceInterface));}}private static T CollectionObject load(final ClassT serviceInterface) {CollectionObject result new LinkedList();for (T each : ServiceLoader.load(serviceInterface)) {result.add(each);}return result;}/*** 获取服务实例* * param 服务接口* param T 服务类型* return 服务实例*/public static T CollectionT getServiceInstances(final ClassT serviceInterface) {return null serviceInterface.getAnnotation(SingletonSPI.class) ? createNewServiceInstances(serviceInterface) : getSingletonServiceInstances(serviceInterface);}SneakyThrows(ReflectiveOperationException.class)SuppressWarnings(unchecked)private static T CollectionT createNewServiceInstances(final ClassT serviceInterface) {if (!SERVICES.containsKey(serviceInterface)) {return Collections.emptyList();}CollectionObject services SERVICES.get(serviceInterface);if (services.isEmpty()) {return Collections.emptyList();}CollectionT result new LinkedList();for (Object each : services) {// 通过反射新建实例result.add((T) each.getClass().getDeclaredConstructor().newInstance());}return result;}SuppressWarnings(unchecked)private static T CollectionT getSingletonServiceInstances(final ClassT serviceInterface) {return (CollectionT) SERVICES.getOrDefault(serviceInterface, Collections.emptyList());}
}