Mp Ds的源码拆解
DynamicDataSourceCreatorAutoConfiguration(数据源创造者配置类)
DefaultDataSourceCreator(数据源创造者管理容器)
下方代码会声明DataSourceCreator的实现类,比如DruidDataSourceCreator(存在Druid数据源时, 加入创建器)
DynamicDataSourceAutoConfiguration(核心加载配置类)
当开启了动态数据源
spring.datasource.dynamic.enabled: true
DynamicDataSourceProperties(主配置读取)
datasource字段维护了数据源的配置,他的value为DataSourceProperty
DataSourceProperty
包含连接必要的参数,如用户名密码
可以进行字符串解密,保证连接信息安全,ENC的示例代码如下
import org.jasypt.encryption.pbe.StandardPBEStringEncryptor;
import org.jasypt.encryption.pbe.config.EnvironmentStringPBEConfig;
public class JasyptEncryptorUtils {
// 加密密钥(建议通过环境变量注入,不要硬编码)
private static final String ENCRYPT_KEY = "my-secret-key-123";
// 初始化加密器
private static StandardPBEStringEncryptor initEncryptor() {
StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor();
EnvironmentStringPBEConfig config = new EnvironmentStringPBEConfig();
config.setPassword(ENCRYPT_KEY); // 设置加密密钥
config.setAlgorithm("PBEWithMD5AndDES"); // 加密算法
config.setKeyObtentionIterations(1000); // 哈希迭代次数
encryptor.setConfig(config);
return encryptor;
}
/**
* 加密明文
*/
public static String encrypt(String plainText) {
StandardPBEStringEncryptor encryptor = initEncryptor();
return encryptor.encrypt(plainText);
}
/**
* 解密密文
*/
public static String decrypt(String encryptedText) {
StandardPBEStringEncryptor encryptor = initEncryptor();
return encryptor.decrypt(encryptedText);
}
public static void main(String[] args) {
// 示例:加密
String originalText = "Hello, World!";
String encryptedText = encrypt(originalText);
System.out.println("加密后: " + encryptedText); // 输出类似 "E8Yz3pL4Z3g5jK7v6bB1Ww=="
// 示例:解密
String decryptedText = decrypt(encryptedText);
System.out.println("解密后: " + decryptedText); // 输出 "Hello, World!"
}
}
DynamicDataSourceProvider(数据源信息提供者)
默认为YmlDynamicDataSourceProvider,也就是会从yml文件中加载数据源信息
YmlDynamicDataSourceProvider(yml数据源提供)
createDataSourceMap方法,该方法由父类提供
这里注入的DefaultDataSourceCreator类,查看文章前面章节的说明,继续调用createDataSource
核心为第68行,依次创建数据源
DruidDataSourceCreator(Druid数据源构造)
DruidDataSourceCreator如下,这里可以从mp ds的配置中读取druid配置(spring.datasource.dynamic.druid)。
但是这里需要改造,应该从spring.datasource.druid中读取,没必要重复配置
第95行,初始化数据源,Druid的代码就不分析了
自定义DataSourceProvider
可继承AbstractDataSourceProvider类,并手动注入该类。如TenantDataSourceJdbcProvider
在启动加载的时候会自动去查数据源并加载
DynamicRoutingDataSource(核心动态数据源组件)
核心方法determineDataSource(当获取connection时调用,取出不同的连接对象)
被调用自父类,重写了getConnection方法
从线程变量获取dsKey,这个线程变量可以使用提供的@Ds来修改,也可以根据自己实现AOP来修改ds的值,这个是数据源的核心
根据dsKey去获取初始化好的数据源并返回,完成数据源的获取,最后通过数据源getConnection()返回可用的数据库连接
启动时加载,初始化连接
通过provider调用loadDataSources,如果自己实现provider,默认是上面提到的YmlDynamicDataSourceProvider
DsProcessor(数据源过程处理,链式设计模式)
依次执行顺序为 DsHeaderProcessor、DsSessionProcessor、DsSpelExpressionProcessor
可自定义继承DsProcessor类,实现业务逻辑
DynamicDataSourceAnnotationInterceptor(拦截器)
AOP拦截器,根据@Ds进行拦截
核心方法invoke
第58行,determineDatasource方法,用于返回数据源标识
根据链式dsProcess依次调用,