Spring Boot 多数据源
来源:互联网 发布:淘宝炸鱼鱼雷在哪卖 编辑:程序博客网 时间:2024/05/20 09:09
上篇文章介绍了如何手工使用Java代码将对象注册到Spring中,为本文“多数据源”做了基础。
下面一个Java类是我已经写好的根据配置文件动态创建多dataSource的代码,其原理也很简单,就是读取配置文件,根据配置文件中配置的数据源数量,动态创建dataSource并注册到Spring中。
代码如下:
package org.springboot.sample.config;import java.util.HashMap;import java.util.Map;import java.util.Map.Entry;import javax.sql.DataSource;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.BeansException;import org.springframework.beans.MutablePropertyValues;import org.springframework.beans.factory.annotation.AnnotatedGenericBeanDefinition;import org.springframework.beans.factory.config.BeanDefinition;import org.springframework.beans.factory.config.BeanDefinitionHolder;import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;import org.springframework.beans.factory.support.BeanDefinitionRegistry;import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;import org.springframework.beans.factory.support.BeanNameGenerator;import org.springframework.boot.bind.RelaxedPropertyResolver;import org.springframework.context.EnvironmentAware;import org.springframework.context.annotation.AnnotationBeanNameGenerator;import org.springframework.context.annotation.AnnotationConfigUtils;import org.springframework.context.annotation.AnnotationScopeMetadataResolver;import org.springframework.context.annotation.Configuration;import org.springframework.context.annotation.ScopeMetadata;import org.springframework.context.annotation.ScopeMetadataResolver;import org.springframework.core.env.Environment;/** * 动态创建多数据源注册到Spring中 * * @author 单红宇(365384722) * @myblog http://blog.csdn.net/catoop/ * @create 2016年1月22日 */@Configurationpublic class MultipleDataSourceBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor, EnvironmentAware { private static final Logger logger = LoggerFactory .getLogger(MultipleDataSourceBeanDefinitionRegistryPostProcessor.class); // 如配置文件中未指定数据源类型,使用该默认值 private static final Object DATASOURCE_TYPE_DEFAULT = "org.apache.tomcat.jdbc.pool.DataSource";// private static final Object DATASOURCE_TYPE_DEFAULT = "com.zaxxer.hikari.HikariDataSource"; private ScopeMetadataResolver scopeMetadataResolver = new AnnotationScopeMetadataResolver(); private BeanNameGenerator beanNameGenerator = new AnnotationBeanNameGenerator(); // 存放DataSource配置的集合,模型<dataSourceName,dataSourceMap> private Map<String, Map<String, Object>> dataSourceMap = new HashMap<>(); @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { logger.info("Invoke Metho postProcessBeanFactory"); beanFactory.getBeanDefinition("dataSource").setPrimary(true); BeanDefinition bd = null; Map<String, Object> dsMap = null; for (Entry<String, Map<String, Object>> entry : dataSourceMap.entrySet()) { bd = beanFactory.getBeanDefinition(entry.getKey()); MutablePropertyValues mpv = bd.getPropertyValues(); dsMap = entry.getValue(); mpv.addPropertyValue("driverClassName", dsMap.get("url")); mpv.addPropertyValue("url", dsMap.get("url")); mpv.addPropertyValue("username", dsMap.get("username")); mpv.addPropertyValue("password", dsMap.get("password")); } } @SuppressWarnings("unchecked") @Override public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException { logger.info("Invoke Metho postProcessBeanDefinitionRegistry"); try { if(!dataSourceMap.isEmpty()){ for (Entry<String, Map<String, Object>> entry : dataSourceMap.entrySet()) { Object type = entry.getValue().get("type"); if(type == null) type = DATASOURCE_TYPE_DEFAULT;// 默认DataSource registerBean(registry, entry.getKey(), (Class<? extends DataSource>)Class.forName(type.toString())); } } } catch (ClassNotFoundException e) { e.printStackTrace(); } } /** * 注册Bean到Spring * * @param registry * @param name * @param beanClass * @author SHANHY * @create 2016年1月22日 */ private void registerBean(BeanDefinitionRegistry registry, String name, Class<?> beanClass) { AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(beanClass); ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd); abd.setScope(scopeMetadata.getScopeName()); // 可以自动生成name String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, registry)); AnnotationConfigUtils.processCommonDefinitionAnnotations(abd); BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName); BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, registry); } /** * 加载多数据源配置 */ @Override public void setEnvironment(Environment env) { RelaxedPropertyResolver propertyResolver = new RelaxedPropertyResolver(env, "custom.datasource."); String dsPrefixs = propertyResolver.getProperty("names"); for (String dsPrefix : dsPrefixs.split(",")) {// 多个数据源 Map<String, Object> dsMap = propertyResolver.getSubProperties(dsPrefix + "."); dataSourceMap.put(dsPrefix, dsMap); } }}
将该Java文件直接添加到项目中便可,无其他任何代码耦合,就是单纯一个类。
再来看一下在配置文件中配置多数据源的方法:
# 主数据源,默认的spring.datasource.type=com.zaxxer.hikari.HikariDataSourcespring.datasource.driver-class-name=com.mysql.jdbc.Driverspring.datasource.url=jdbc:mysql://localhost:3306/testspring.datasource.username=rootspring.datasource.password=123456# 更多数据源custom.datasource.names=ds1,ds2,ds3custom.datasource.ds1.type=com.zaxxer.hikari.HikariDataSourcecustom.datasource.ds1.driver-class-name=com.mysql.jdbc.Drivercustom.datasource.ds1.url=jdbc:mysql://localhost:3306/testcustom.datasource.ds1.username=rootcustom.datasource.ds1.password=123456custom.datasource.ds2.type=com.zaxxer.hikari.HikariDataSourcecustom.datasource.ds2.driver-class-name=com.mysql.jdbc.Drivercustom.datasource.ds2.url=jdbc:mysql://localhost:3306/testcustom.datasource.ds2.username=rootcustom.datasource.ds2.password=123456custom.datasource.ds3.type=com.zaxxer.hikari.HikariDataSourcecustom.datasource.ds3.driver-class-name=com.mysql.jdbc.Drivercustom.datasource.ds3.url=jdbc:mysql://localhost:3306/testcustom.datasource.ds3.username=rootcustom.datasource.ds3.password=123456# 下面为连接池的补充设置,应用到上面所有数据源中spring.datasource.maximum-pool-size=100spring.datasource.max-idle=10spring.datasource.max-wait=10000spring.datasource.min-idle=5spring.datasource.initial-size=5spring.datasource.validation-query=SELECT 1spring.datasource.test-on-borrow=falsespring.datasource.test-while-idle=truespring.datasource.time-between-eviction-runs-millis=18800
配置文件包括1个主数据源和多个数据源,其中主数据源在Spring中的beanName默认为dataSource,另外几个数据源的beanName分包为:ds1、ds2、ds3,大家看一下配置的规则,想必不用多说。
其中datasource的type属性可以具体指定到我们需要的数据源上面,不指定情况下默认为:org.apache.tomcat.jdbc.pool.DataSource
当然你也可以把这些数据源配置到主dataSource数据库中,然后读取数据库生成多数据源。当然这样做的必要性并不大,难不成数据源还会经常变吗。
在需要应用dataSource的地方需要指定名称,如:
// 方法参数注入方式public void testDataSource(@Qualifier("ds1") DataSource myDataSource, @Qualifier("dataSource") DataSource dataSource) {}
或者
// 类成员属性注入方式@Autowired@Qualifier("ds1")private DataSource dataSource1;@Resource(name = "ds2")private DataSource dataSource2;
本文共享的代码可以直接使用了,大家可以根据自己需要进行调整。
然而我们在项目中不一定需要直接使用dataSource的,大家都习惯使用JDBC的jdbcTemplate、Mybatis的sqlSessionTemplate,再或者就是以Mybatis为例直接动态代理到Mapper接口上。
那么如何做到完全动态数据源呢,以至于实现我们可以为同一个Java类的不同方法,分别指定使用不同的数据源?下篇文章将为大家揭晓。
- Spring Boot 多数据源
- Spring Boot 多数据源
- Spring Boot多数据源
- Spring Boot 多数据源
- Spring Boot 多数据源
- Spring Boot 多数据源
- spring boot多数据源
- Spring Boot 多数据源
- spring(spring-boot) + mybatis多数据源
- spring boot mybatis 多数据源异常
- spring boot Mybatis多数据源配置
- spring boot多数据源配置
- Spring Boot 动态多数据源
- spring boot 多数据源动态切换
- spring boot 多数据源配置
- spring boot+mybatis 多数据源切换
- spring boot+mybatis 多数据源切换
- spring boot + mybatis 多数据源配置
- Fragment获取context
- [神经网络]1.4-Using neural nets to recognize handwritten digits-A simple network to classify ...(翻译)
- oj效率问题
- SetWindowPos函数详解
- L2TP协议
- Spring Boot 多数据源
- 插件大集合
- x265-1.7版本-common/frame.h注释
- 【xv6学习之番外篇】详解struct Env 与 struct Trapframe
- tomcat与nginx、Apache整合
- HDU 1098 (数学_特殊值+抽屉原理)
- hdu 3294 Girls' research Manacher回文串
- uva 10564 - Paths through the Hourglass 沙漏里的路径 最优解+路径输出
- 关于 Mac OS 本地安装 Mysql 的一些坑