和方案一区别:
spring:
datasource:
primary:
url: jdbc:mysql://127.0.0.1:3306/test?characterEncoding=utf-8
username: zhangzx
password: 123
driverClassName: com.mysql.cj.jdbc.Driver
slave1:
url: jdbc:mysql://127.0.0.1:3306/slave1?characterEncoding=utf-8
username: zhangzx
password: 123
driverClassName: com.mysql.cj.jdbc.Driver
names: primary,slave1
package com.itw.learn;
import com.itw.learn.config.DynamicDataSourceRegister;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Import;
import java.util.Arrays;
@MapperScan("com.itw.learn.dao")
@SpringBootApplication
//需要导入这个注册类,初始化config对象之后,初始化我们的import对象
@Import(DynamicDataSourceRegister.class)
public class MyAppDemo {
public static void main(String[] args) {
ApplicationContext ctx = SpringApplication.run(MyAppDemo.class, args);
}
@Bean
public CommandLineRunner commandLineRunner(ApplicationContext ctx) {
// 目的是
return args -> {
System.out.println("来看看 SpringBoot 默认为我们提供的 Bean:");
String[] beanNames = ctx.getBeanDefinitionNames();
Arrays.stream(beanNames)
.filter(t->t.equals("PrimaryDatasource"))
.forEach(System.out::println);
//Arrays.sort(beanNames);
//Arrays.stream(beanNames).forEach(System.out::println);
};
}
}
数据源 注册类:
package com.itw.learn.config;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.context.EnvironmentAware;
import org.springframework.context.ResourceLoaderAware;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.env.Environment;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.type.AnnotationMetadata;
import javax.sql.DataSource;
import java.util.HashMap;
import java.util.Map;
public class DynamicDataSourceRegister implements ImportBeanDefinitionRegistrar,EnvironmentAware , ResourceLoaderAware {
private Environment environment;
private ResourceLoader resourceLoader;
//默认数据源
private DataSource defaultDataSource;
//所有的数据源
private Map<String, DataSource> targetDataSources = new HashMap<>();
void initDefaultDataSource(){
defaultDataSource = DataSourceBuilder
.create()
.driverClassName(environment.getProperty("spring.datasource.primary.driver-class-name"))
.url(environment.getProperty("spring.datasource.primary.url"))
.username( environment.getProperty("spring.datasource.primary.username"))
.password(environment.getProperty("spring.datasource.primary.password"))
.build();
}
void initTargetDataSources() {
// 读取配置文件获取全部数据源
String dsPrefixs = environment.getProperty("spring.datasource.names");
for (String dsPrefix : dsPrefixs.split(",")) {
// 多个数据源
DataSource ds =DataSourceBuilder
.create()
.driverClassName(environment.getProperty("spring.datasource." + dsPrefix + ".driver-class-name"))
.url(environment.getProperty("spring.datasource." + dsPrefix + ".url"))
.username( environment.getProperty("spring.datasource." + dsPrefix + ".username"))
.password(environment.getProperty("spring.datasource." + dsPrefix + ".password"))
.build();
targetDataSources.put(dsPrefix,ds);
}
}
@Override
public void setEnvironment(Environment environment) {
this.environment = environment;
initDefaultDataSource();
initTargetDataSources();
}
@Override
public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry beanDefinitionRegistry) {
//创建DynamicDataSource
GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
beanDefinition.setBeanClass(DynamicDataSource.class);
beanDefinition.setSynthetic(true);
MutablePropertyValues mpv = beanDefinition.getPropertyValues();
mpv.addPropertyValue("defaultTargetDataSource", defaultDataSource);
mpv.addPropertyValue("targetDataSources", targetDataSources);
//注册 - BeanDefinitionRegistry
beanDefinitionRegistry.registerBeanDefinition("dataSource", beanDefinition);
}
//这个ResourceLoaderAware接口的实现是 不需要的,可以去掉
@Override
public void setResourceLoader(ResourceLoader resourceLoader) {
this.resourceLoader = resourceLoader;
}
}
该方案的优点:
很明显,只是做了数据源的注入,所以我们还是按往常一样使用mybatis就可以了,不用像方案一,需要将扫描xml的位置在代码中编写。
其次:我们如果注册多个数据源,只需要修改配置文件即可,代码是不需要修改的。