SpringBoot 自定义多数据源 starter 组件

本案例我们使用多数据源封装成一个starter组件,以方便使用多数据源访问数据库的操作

创建一个普通Java项目,引入SpringBoot相关的依赖

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http: maven.apache.org pom 4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"          xsi:schemalocation="http://maven.apache.org/POM/4.0.0&#xA0;https://maven.apache.org/xsd/maven-4.0.0.xsd">
&#xA0;&#xA0;&#xA0;&#xA0;<modelversion>4.0.0</modelversion>
&#xA0;&#xA0;&#xA0;&#xA0;<parent>
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;<groupid>org.springframework.boot</groupid>
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;<artifactid>spring-boot-starter-parent</artifactid>
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;<version>2.6.3</version>
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;<relativepath>
&#xA0;&#xA0;&#xA0;&#xA0;</relativepath></parent>
&#xA0;&#xA0;&#xA0;&#xA0;<groupid>com.gitee.kenewstar.multi.datasource</groupid>
&#xA0;&#xA0;&#xA0;&#xA0;<artifactid>multi-datasource-spring-boot-starter</artifactid>
&#xA0;&#xA0;&#xA0;&#xA0;<version>0.0.1</version>
&#xA0;&#xA0;&#xA0;&#xA0;<name>multi-datasource-spring-boot-starter</name>
&#xA0;&#xA0;&#xA0;&#xA0;<description>multi-datasource-spring-boot-starter</description>
&#xA0;&#xA0;&#xA0;&#xA0;<properties>
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;<java.version>1.8</java.version>
&#xA0;&#xA0;&#xA0;&#xA0;</properties>
&#xA0;&#xA0;&#xA0;&#xA0;<dependencies>
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;<dependency>
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;<groupid>org.springframework.boot</groupid>
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;<artifactid>spring-boot-starter</artifactid>
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;</dependency>
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;<dependency>
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;<groupid>org.springframework.boot</groupid>
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;<artifactid>spring-boot-configuration-processor</artifactid>
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;<optional>true</optional>
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;</dependency>

&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;<dependency>
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;<groupid>org.springframework.boot</groupid>
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;<artifactid>spring-boot-starter-jdbc</artifactid>
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;</dependency>
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;<dependency>
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;<groupid>org.springframework.boot</groupid>
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;<artifactid>spring-boot-starter-aop</artifactid>
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;</dependency>
&#xA0;&#xA0;&#xA0;&#xA0;</dependencies>

</project xmlns="http:>

创建常量类和注解

public&#xA0;interface&#xA0;Const&#xA0;{

&#xA0;&#xA0;&#xA0;&#xA0;String&#xA0;DEFAULT&#xA0;=&#xA0;"default";

&#xA0;&#xA0;&#xA0;&#xA0;String&#xA0;MULTI_DS&#xA0;=&#xA0;"multiDataSource";

&#xA0;&#xA0;&#xA0;&#xA0;String&#xA0;CONFIG_PREFIX&#xA0;=&#xA0;"spring.datasource.multi";

}

数据源注解

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public&#xA0;@interface&#xA0;DataSource&#xA0;{

&#xA0;&#xA0;&#xA0;&#xA0;String&#xA0;value()&#xA0;default&#xA0;Const.DEFAULT;

}

创建多数据源属性类

主要用于存储SpringBoot配置文件中配置的数据源属性

@Component
@ConfigurationProperties(prefix&#xA0;=&#xA0;Const.CONFIG_PREFIX)
public&#xA0;class&#xA0;MultiDataSourceProperties&#xA0;{

&#xA0;&#xA0;&#xA0;&#xA0;private&#xA0;Map<string, datasourceprop>&#xA0;dataSourcePropMap;

&#xA0;&#xA0;&#xA0;&#xA0;public&#xA0;Map<string, datasourceprop>&#xA0;getDataSourcePropMap()&#xA0;{
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;return&#xA0;dataSourcePropMap;
&#xA0;&#xA0;&#xA0;&#xA0;}

&#xA0;&#xA0;&#xA0;&#xA0;public&#xA0;void&#xA0;setDataSourcePropMap(Map<string, datasourceprop>&#xA0;dataSourcePropMap)&#xA0;{
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;this.dataSourcePropMap&#xA0;=&#xA0;dataSourcePropMap;
&#xA0;&#xA0;&#xA0;&#xA0;}
}

public&#xA0;class&#xA0;DataSourceProp&#xA0;extends&#xA0;HashMap<string, string>&#xA0;{

}
</string, string></string, datasourceprop></string, datasourceprop></string, datasourceprop>

创建数据源key的切换工具

主要用于设置当前线程下数据源切换时的数据源唯一标识key,以便获取指定的数据源

public&#xA0;class&#xA0;DynamicDataSourceHolder&#xA0;{

&#xA0;&#xA0;&#xA0;&#xA0;private&#xA0;static&#xA0;final&#xA0;ThreadLocal<string>&#xA0;DATA_SOURCE_THEAD_LOCAL&#xA0;=
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;ThreadLocal.withInitial(()&#xA0;->&#xA0;Const.DEFAULT);

&#xA0;&#xA0;&#xA0;&#xA0;public&#xA0;static&#xA0;String&#xA0;getDataSource()&#xA0;{
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;return&#xA0;DATA_SOURCE_THEAD_LOCAL.get();
&#xA0;&#xA0;&#xA0;&#xA0;}

&#xA0;&#xA0;&#xA0;&#xA0;public&#xA0;static&#xA0;void&#xA0;setDataSource(String&#xA0;dataSource)&#xA0;{
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;DATA_SOURCE_THEAD_LOCAL.set(dataSource);
&#xA0;&#xA0;&#xA0;&#xA0;}

&#xA0;&#xA0;&#xA0;&#xA0;public&#xA0;static&#xA0;void&#xA0;remove()&#xA0;{
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;DATA_SOURCE_THEAD_LOCAL.remove();
&#xA0;&#xA0;&#xA0;&#xA0;}

}
</string>

创建多数据源类

创建多数据源类继承 AbstractRoutingDataSource类,重写 determineCurrentLookupKey()方法,用于获取当前线程中的指定的数据源key,通过该key拿到对应的数据源对象

public&#xA0;class&#xA0;MultiDataSource&#xA0;extends&#xA0;AbstractRoutingDataSource&#xA0;{

&#xA0;&#xA0;&#xA0;&#xA0;private&#xA0;static&#xA0;final&#xA0;Logger&#xA0;LOGGER&#xA0;=&#xA0;Logger.getLogger(MultiDataSource.class.getName());

&#xA0;&#xA0;&#xA0;&#xA0;@Override
&#xA0;&#xA0;&#xA0;&#xA0;protected&#xA0;Object&#xA0;determineCurrentLookupKey()&#xA0;{
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;String&#xA0;key&#xA0;=&#xA0;DynamicDataSourceHolder.getDataSource();
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;LOGGER.info("DataSource&#xA0;key&#xA0;--->&#xA0;"&#xA0;+&#xA0;key);
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;return&#xA0;key;
&#xA0;&#xA0;&#xA0;&#xA0;}

}

创建多数据源的切面类

切面类主要用于获取被数据与注解指定的方法,拿到其注解中的属性值,再设置到数据源key设置组件中,方便数据源类获取该key

需使用 @Order设置切面优先级,否则设置无效

@Aspect
@Order(100)
public&#xA0;class&#xA0;DynamicDataSourceAdviser&#xA0;{

&#xA0;&#xA0;&#xA0;&#xA0;@Pointcut("@annotation(com.gitee.kenewstar.multi.datasource.common.DataSource)")
&#xA0;&#xA0;&#xA0;&#xA0;public&#xA0;void&#xA0;pointcut(){};

&#xA0;&#xA0;&#xA0;&#xA0;@Around("pointcut()")
&#xA0;&#xA0;&#xA0;&#xA0;public&#xA0;Object&#xA0;around(ProceedingJoinPoint&#xA0;point)&#xA0;throws&#xA0;Throwable&#xA0;{

&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;try&#xA0;{
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;MethodSignature&#xA0;methodSignature&#xA0;=&#xA0;(MethodSignature)&#xA0;point.getSignature();
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;//&#x83B7;&#x53D6;&#x88AB;&#x4EE3;&#x7406;&#x7684;&#x65B9;&#x6CD5;&#x5BF9;&#x8C61;
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;Method&#xA0;targetMethod&#xA0;=&#xA0;methodSignature.getMethod();
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;//&#xA0;&#x83B7;&#x53D6;&#x6570;&#x636E;&#x6E90;&#x6CE8;&#x89E3;
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;DataSource&#xA0;ds&#xA0;=&#xA0;targetMethod.getAnnotation(DataSource.class);
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;if&#xA0;(Objects.nonNull(ds))&#xA0;{
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;DynamicDataSourceHolder.setDataSource(ds.value());
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;}
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;return&#xA0;point.proceed();
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;}&#xA0;finally&#xA0;{
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;DynamicDataSourceHolder.remove();
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;}

&#xA0;&#xA0;&#xA0;&#xA0;}

}

创建数据源配置类

@Configuration
@EnableConfigurationProperties(MultiDataSourceProperties.class)
public&#xA0;class&#xA0;MultiDataSourceConfig&#xA0;{

&#xA0;&#xA0;&#xA0;&#xA0;public&#xA0;static&#xA0;final&#xA0;String&#xA0;DS_TYPE&#xA0;=&#xA0;"dsType";

&#xA0;&#xA0;&#xA0;&#xA0;@Resource
&#xA0;&#xA0;&#xA0;&#xA0;private&#xA0;MultiDataSourceProperties&#xA0;multiDataSourceProperties;

&#xA0;&#xA0;&#xA0;&#xA0;private&#xA0;DataSource&#xA0;createDs(DataSourceProp&#xA0;dsProp)&#xA0;{
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;DataSource&#xA0;dataSource&#xA0;=&#xA0;null;
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;try&#xA0;{
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;Class<?>&#xA0;dsClass&#xA0;=&#xA0;Class.forName(dsProp.get(DS_TYPE));
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;if&#xA0;(DataSource.class.isAssignableFrom(dsClass))&#xA0;{
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;dataSource&#xA0;=&#xA0;(DataSource)&#xA0;dsClass.getConstructor().newInstance();

&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;DataSource&#xA0;finalDataSource&#xA0;=&#xA0;dataSource;
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;ReflectionUtils.doWithFields(dsClass,&#xA0;field&#xA0;->&#xA0;{
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;field.setAccessible(true);
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;field.set(finalDataSource,&#xA0;dsProp.get(field.getName()));
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;},&#xA0;field&#xA0;->&#xA0;{
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;if&#xA0;(Objects.equals(dsProp.get(DS_TYPE),&#xA0;field.getName()))&#xA0;{
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;return&#xA0;false;
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;}
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;return&#xA0;Objects.nonNull(dsProp.get(field.getName()));
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;});

&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;}

&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;}&#xA0;catch&#xA0;(Exception&#xA0;e)&#xA0;{
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;throw&#xA0;new&#xA0;RuntimeException(e);
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;}
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;return&#xA0;dataSource;
&#xA0;&#xA0;&#xA0;&#xA0;}

&#xA0;&#xA0;&#xA0;&#xA0;@Bean(Const.MULTI_DS)
&#xA0;&#xA0;&#xA0;&#xA0;@Primary
&#xA0;&#xA0;&#xA0;&#xA0;public&#xA0;DataSource&#xA0;multiDataSource()&#xA0;{
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;MultiDataSource&#xA0;multiDataSource&#xA0;=&#xA0;new&#xA0;MultiDataSource();

&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;Map<object, object>&#xA0;dataSourceMap&#xA0;=&#xA0;new&#xA0;HashMap<>(multiDataSourceProperties.getDataSourcePropMap().size());
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;Map<string, datasourceprop>&#xA0;dataSourcePropMap&#xA0;=&#xA0;multiDataSourceProperties.getDataSourcePropMap();
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;dataSourcePropMap.forEach((lookupKey,dsProp)&#xA0;->&#xA0;{
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;dataSourceMap.put(lookupKey,&#xA0;createDs(dsProp));
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;});

&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;multiDataSource.setTargetDataSources(dataSourceMap);
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;multiDataSource.setDefaultTargetDataSource(dataSourceMap.get(Const.DEFAULT));
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;return&#xA0;multiDataSource;
&#xA0;&#xA0;&#xA0;&#xA0;}

&#xA0;&#xA0;&#xA0;&#xA0;@Bean
&#xA0;&#xA0;&#xA0;&#xA0;public&#xA0;DataSourceTransactionManager&#xA0;dataSourceTransactionManager(
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;@Qualifier(Const.MULTI_DS)&#xA0;DataSource&#xA0;multiDataSource)&#xA0;{

&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;DataSourceTransactionManager&#xA0;tx&#xA0;=&#xA0;new&#xA0;DataSourceTransactionManager();
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;tx.setDataSource(multiDataSource);
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;return&#xA0;tx;
&#xA0;&#xA0;&#xA0;&#xA0;}

&#xA0;&#xA0;&#xA0;&#xA0;@Bean
&#xA0;&#xA0;&#xA0;&#xA0;public&#xA0;DynamicDataSourceAdviser&#xA0;dynamicDataSourceAdviser()&#xA0;{
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;return&#xA0;new&#xA0;DynamicDataSourceAdviser();
&#xA0;&#xA0;&#xA0;&#xA0;}

}
</string, datasourceprop></object, object>

配置spring.factories文件

在resources目录下创建 META-INF目录,在该目录创建 spring.factories

SpringBoot 自定义多数据源 starter 组件

文件内容如下:

设置key为开启自动配置的注解全路径名,后面的value值为配置类全路径名,本starter组件中为数据源配置类,如有多个配置类,则以逗号分隔,以反斜杆表示忽略换行

org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.gitee.kenewstar.multi.datasource.config.MultiDataSourceConfig

这样我们封装的一个简单的多数据源starter组件就完成了,只需进行maven打包即可在本地使用

maven命令: mvn clean install

使用示例

引入打包后的依赖

<dependency>
&#xA0;&#xA0;&#xA0;&#xA0;<groupid>com.gitee.kenewstar.multi.datasource</groupid>
&#xA0;&#xA0;&#xA0;&#xA0;<artifactid>multi-datasource-spring-boot-starter</artifactid>
&#xA0;&#xA0;&#xA0;&#xA0;<version>0.0.1</version>
</dependency>

修改SpringBoot全局配置文件

default为默认数据源,必须配置, master为可选数据源,名称可自定义。

数据源的属性名称为对应的dsType数据源类型的属性字段

spring:
&#xA0;&#xA0;datasource:
&#xA0;&#xA0;&#xA0;&#xA0;multi:
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;data-source-prop-map:
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;default:
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;dsType:&#xA0;com.zaxxer.hikari.HikariDataSource
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;jdbcUrl:&#xA0;jdbc:mysql://localhost:3306/test
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;username:&#xA0;root
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;password:&#xA0;kenewstar
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;master:
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;dsType:&#xA0;com.zaxxer.hikari.HikariDataSource
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;jdbcUrl:&#xA0;jdbc:mysql://localhost:3306/test2
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;username:&#xA0;root
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;password:&#xA0;kenewstar

使用数据源

直接在指定的方法上添加 @DataSource注解即可,注解的默认值为default,数据源的切换通过注解的值进行切换。值为 application.yml中配置的default,master等

@Service
public&#xA0;class&#xA0;PersonService&#xA0;{

&#xA0;&#xA0;&#xA0;&#xA0;@Resource
&#xA0;&#xA0;&#xA0;&#xA0;private&#xA0;PersonMapper&#xA0;personMapper;

&#xA0;&#xA0;&#xA0;&#xA0;@DataSource("master")
&#xA0;&#xA0;&#xA0;&#xA0;@Transactional(rollbackFor&#xA0;=&#xA0;Exception.class)
&#xA0;&#xA0;&#xA0;&#xA0;public&#xA0;void&#xA0;insertPerson()&#xA0;{
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;personMapper.insert(new&#xA0;Person(null,&#xA0;"kk",&#xA0;12));
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;personMapper.insert(new&#xA0;Person(null,&#xA0;"kk",&#xA0;12));
&#xA0;&#xA0;&#xA0;&#xA0;}

}
@Service
public&#xA0;class&#xA0;PersonService&#xA0;{

&#xA0;&#xA0;&#xA0;&#xA0;@Resource
&#xA0;&#xA0;&#xA0;&#xA0;private&#xA0;PersonMapper&#xA0;personMapper;

&#xA0;&#xA0;&#xA0;&#xA0;@DataSource("master")
&#xA0;&#xA0;&#xA0;&#xA0;@Transactional(rollbackFor&#xA0;=&#xA0;Exception.class)
&#xA0;&#xA0;&#xA0;&#xA0;public&#xA0;void&#xA0;insertPerson()&#xA0;{
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;personMapper.insert(new&#xA0;Person(null,&#xA0;"kk",&#xA0;12));
&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;&#xA0;personMapper.insert(new&#xA0;Person(null,&#xA0;"kk",&#xA0;12));
&#xA0;&#xA0;&#xA0;&#xA0;}
}

多数据源starter组件源码地址:

https://gitee.com/kenewstar/multi-datasource-spring-boot-starter

Original: https://blog.csdn.net/m0_71777195/article/details/127818095
Author: 肥肥技术宅
Title: SpringBoot 自定义多数据源 starter 组件

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/654458/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球