mybatis |
您所在的位置:网站首页 › springboot整合mybatis-plus › mybatis |
文章已收录到我的Github精选,欢迎Star:https://github.com/yehongzhi/learningSummary 写在前面上一篇文章大致介绍了dynamic-datasource的功能,用起来的确很方便,只需要一个@DS注解,加上一些简单的配置即可完成多数据源的切换。究竟是怎么做到的呢,底层是怎么实现呢?带着这个疑问,一起研究了一下源码。 由于框架本身功能点比较多,有很多小功能比如支持spel、正则表达式匹配,动态增删数据源这种功能的源码就不去细讲了。我们只关心核心的功能,就是多数据源的切换。 源码解析首先我们都记得,一开始需要引入spring-boot-starter: com.baomidou dynamic-datasource-spring-boot-starter 3.3.0一般starter自动配置,都是从 META-INF/spring.factories文件中指定自动配置类: org.springframework.boot.autoconfigure.EnableAutoConfiguration=\com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DynamicDataSourceAutoConfiguration接着打开这个类: /** * 动态数据源核心自动配置类 * * @author TaoYu Kanyuxia * @see DynamicDataSourceProvider * @see DynamicDataSourceStrategy * @see DynamicRoutingDataSource * @since 1.0.0 */@Slf4j@Configuration@AllArgsConstructor//以spring.datasource.dynamic为前缀读取配置@EnableConfigurationProperties(DynamicDataSourceProperties.class)//在SpringBoot注入DataSourceAutoConfiguration的bean自动配置之前,先加载注入当前这个类的bean到容器中@AutoConfigureBefore(DataSourceAutoConfiguration.class)//引入了Druid的autoConfig和各种数据源连接池的Creator@Import(value = {DruidDynamicDataSourceConfiguration.class, DynamicDataSourceCreatorAutoConfiguration.class})//条件加载,当前缀是"spring.datasource.dynamic"配置的时候启用这个autoConfig@ConditionalOnProperty(prefix = DynamicDataSourceProperties.PREFIX, name = "enabled", havingValue = "true", matchIfMissing = true)public class DynamicDataSourceAutoConfiguration { private final DynamicDataSourceProperties properties; //读取多数据源配置,注入到spring容器中 @Bean @ConditionalOnMissingBean public DynamicDataSourceProvider dynamicDataSourceProvider() { Map datasourceMap = properties.getDatasource(); return new YmlDynamicDataSourceProvider(datasourceMap); } //注册自己的动态多数据源DataSource @Bean @ConditionalOnMissingBean public DataSource dataSource(DynamicDataSourceProvider dynamicDataSourceProvider) { DynamicRoutingDataSource dataSource = new DynamicRoutingDataSource(); dataSource.setPrimary(properties.getPrimary()); dataSource.setStrict(properties.getStrict()); dataSource.setStrategy(properties.getStrategy()); dataSource.setProvider(dynamicDataSourceProvider); dataSource.setP6spy(properties.getP6spy()); dataSource.setSeata(properties.getSeata()); return dataSource; } //AOP切面,对DS注解过的方法进行增强,达到切换数据源的目的 @Role(value = BeanDefinition.ROLE_INFRASTRUCTURE) @Bean @ConditionalOnMissingBean public DynamicDataSourceAnnotationAdvisor dynamicDatasourceAnnotationAdvisor(DsProcessor dsProcessor) { DynamicDataSourceAnnotationInterceptor interceptor = new DynamicDataSourceAnnotationInterceptor(properties.isAllowedPublicOnly(), dsProcessor); DynamicDataSourceAnnotationAdvisor advisor = new DynamicDataSourceAnnotationAdvisor(interceptor); advisor.setOrder(properties.getOrder()); return advisor; } //关于分布式事务加强 @Role(value = BeanDefinition.ROLE_INFRASTRUCTURE) @ConditionalOnProperty(prefix = DynamicDataSourceProperties.PREFIX, name = "seata", havingValue = "false", matchIfMissing = true) @Bean public Advisor dynamicTransactionAdvisor() { AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut(); pointcut.setExpression("@annotation(com.baomidou.dynamic.datasource.annotation.DSTransactional)"); return new DefaultPointcutAdvisor(pointcut, new DynamicTransactionAdvisor()); } //动态参数解析器链 @Bean @ConditionalOnMissingBean public DsProcessor dsProcessor() { DsHeaderProcessor headerProcessor = new DsHeaderProcessor(); DsSessionProcessor sessionProcessor = new DsSessionProcessor(); DsSpelExpressionProcessor spelExpressionProcessor = new DsSpelExpressionProcessor(); headerProcessor.setNextProcessor(sessionProcessor); sessionProcessor.setNextProcessor(spelExpressionProcessor); return headerProcessor; }}我们可以发现,在使用的时候配置的前缀为spring.datasource.dynamic的配置都会被读取到DynamicDataSourceProperties类,作为一个Bean注入到Spring容器。其实这种读取配置文件信息的方式在日常开发中也是很常见的。 @Slf4j@Getter@Setter@ConfigurationProperties(prefix = DynamicDataSourceProperties.PREFIX)public class DynamicDataSourceProperties { public static final String PREFIX = "spring.datasource.dynamic"; public static final String HEALTH = PREFIX + ".health"; /** * 必须设置默认的库,默认master */ private String primary = "master"; /** * 是否启用严格模式,默认不启动. 严格模式下未匹配到数据源直接报错, 非严格模式下则使用默认数据源primary所设置的数据源 */ private Boolean strict = false; /** * 是否使用p6spy输出,默认不输出 */ private Boolean p6spy = false; /** * 是否使用开启seata,默认不开启 */ private Boolean seata = false; /** * seata使用模式,默认AT */ private SeataMode seataMode = SeataMode.AT; /** * 是否使用 spring actuator 监控检查,默认不检查 */ private boolean health = false; /** * 每一个数据源 */ private Map datasource = new LinkedHashMap(); /** * 多数据源选择算法clazz,默认负载均衡算法 */ private Class |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |