spring 动态数据源切换实例

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介: 本文章摘编、转载需要注明来源 http://blog.csdn.net/shadowsick/article/details/8878448我们很多项目中业务都需要涉及到多个数据源,...

本文章摘编、转载需要注明来源 http://blog.csdn.net/shadowsick/article/details/8878448


我们很多项目中业务都需要涉及到多个数据源,最简单的做法就是直接在java代码里面lookup需要的数据源,但是这样的做法很明显耦合度太高了,

而且当逻辑流程不够严谨的时候就会出现各种大家不愿意看到的问题,由于我们现在的大多项目已经离不开spring了,spring也提供各种强大的功能,

很明显这种动态数据源功能也包括在内,具体实现类请看org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource


这里我演示下如何使用spring提供的动态数据源


先写个接口,default设置为null是因为当程序里没有找到相关联的源就会调用默认源

/**
 * 数据源切换接口
 * 
 * @author shadow
 * @create 2013.04.03
 */
public interface DataSourceEntry {

	// 默认数据源
	public final static String DEFAULT_SOURCE = null;

	/**
	 * 还原数据源
	 * 
	 * @param joinPoint
	 */
	public void restore(JoinPoint join);

	/**
	 * 设置数据源
	 * 
	 * @param dataSource
	 */
	public void set(String source);

	/**
	 * 获取数据源
	 * 
	 * @return String
	 */
	public String get();

	/**
	 * 清空数据源
	 */
	public void clear();
}

然后写个实现类,从当前线程里取出对应的数据源名

/**
 * 数据源切换实现类类
 * 
 * @author shadow
 * @create 2013.04.03
 */
public class DataSourceEntryImpl implements DynamicTypeEntry {

	private final static ThreadLocal<String> local = new ThreadLocal<String>();

	public void clear() {
		local.remove();
	}

	public String get() {
		return local.get();
	}

	public void restore(JoinPoint join) {
		local.set(DEFAULT_SOURCE);
	}

	public void set(String source) {
		local.set(source);
	}

}


然后写个继承AbstractRoutingDataSource的类,并注入DataSourceEntry,重写determineCurrentLookupKey模版方法

/**
 * 获取数据源(依赖SPRING框架)
 * 
 * @author shadow
 * @create 2013.04.03
 */
public class DynamicDataSource extends AbstractRoutingDataSource {

	private DataSourceEntry dataSourceEntry;

	@Override
	protected Object determineCurrentLookupKey() {
		return this.dataSourceEntry.get();
	}

	@Resource
	public void setDataSourceEntry(DataSourceEntry dataSourceEntry) {
		this.dataSourceEntry = dataSourceEntry;
	}

}

最后就是配置下xml文件,以后只需要直接管理dynamicDataSource这个接口就可以了,至于他内部是哪个数据源是不需要关注,写的切面还原是为了保证每次调用完另外的数据源

都会还原成默认数据源,防止有的人忘记设置回默认的,导致其他代码出问题

<!-- JDBC模板 -->
	<bean id="jdbcTemplate"
		class="org.springframework.jdbc.core.JdbcTemplate">
		<property name="dataSource" ref="dynamicDataSource" />
	</bean>

	<!-- 获取数据源配置 -->
	<bean
		class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
		<property name="locations">
			<value>classpath:properties/jdbc.properties</value>
		</property>
	</bean>

	<!-- 配置动态数据源 -->
	<bean id="dynamicDataSource"
		class="com.shadow.system.base.source.DynamicDataSource">
		<!-- 通过key-value的形式来关联数据源 -->
		<property name="targetDataSources">
			<map key-type="java.lang.String">
				<entry value-ref="C3P0_MYSQL" key="C3P0_MYSQL"></entry>
				<entry value-ref="C3P0_MYSQL2" key="C3P0_MYSQL2"></entry>
			</map>
		</property>
		<property name="defaultTargetDataSource" ref="C3P0_MYSQL" />
	</bean>

	<!-- JNDI方式 -->
	<bean id="C3P0_MYSQL"
		class="org.springframework.jndi.JndiObjectFactoryBean">
		<property name="resourceRef">
			<value>false</value>
		</property>
		<property name="jndiName">
			<value>${JNDI.template}</value>
		</property>
	</bean>
	
	<!-- JNDI方式 -->
	<bean id="C3P0_MYSQL2"
		class="org.springframework.jndi.JndiObjectFactoryBean">
		<property name="resourceRef">
			<value>false</value>
		</property>
		<property name="jndiName">
			<value>${JNDI.test}</value>
		</property>
	</bean>

	<!-- 配置数据源切换实现类 -->
	<bean id="dataSourceEntry"
		class="com.shadow.system.base.source.DataSourceEntryImpl" />

	<!-- 切面还原默认数据源 -->
	<aop:config>
		<aop:aspect id="dataSourceHolderAdviceAspect"
			ref="dataSourceEntry">
			<aop:after method="restore"
				pointcut="execution(* com.shadow.mvc.service.*Service.*(..))" />
		</aop:aspect>
	</aop:config>

至于程序里如何变换数据源,你可以在切面上检测哪些方法加入before方法,或者在程序里直接使用DataSourceEntry调用set方法,具体的怎么用不作代码说明了

相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
8月前
|
设计模式 Java Spring
【Spring源码】WebSocket做推送动作的底层实例是谁
我们都知道WebSocket可以主动推送消息给用户,那做推送动作的底层实例究竟是谁?我们先整体看下整个模块的组织机构。可以看到handleMessage方法定义了每个消息格式采用不同的消息处理方法,而这些方法该类并**没有实现**,而是留给了子类去实现。
【Spring源码】WebSocket做推送动作的底层实例是谁
|
6月前
|
消息中间件 Java Kafka
Spring boot 自定义kafkaTemplate的bean实例进行生产消息和发送消息
Spring boot 自定义kafkaTemplate的bean实例进行生产消息和发送消息
232 5
|
5月前
|
XML Java 数据库
Spring5入门到实战------10、操作术语解释--Aspectj注解开发实例。AOP切面编程的实际应用
这篇文章是Spring5框架的实战教程,详细解释了AOP的关键术语,包括连接点、切入点、通知、切面,并展示了如何使用AspectJ注解来开发AOP实例,包括切入点表达式的编写、增强方法的配置、代理对象的创建和优先级设置,以及如何通过注解方式实现完全的AOP配置。
|
5月前
|
Java Spring
Spring Boot Admin 离线实例
Spring Boot Admin 离线实例
42 0
|
7月前
|
存储 Java 数据库
Spring Boot中的动态数据源切换
Spring Boot中的动态数据源切换
|
7月前
|
Java Spring
spring基于注解配置数据源
spring基于注解配置数据源
|
7月前
|
Java Maven Spring
Spring中AOP最简单实例-@注解形式
Spring中AOP最简单实例-@注解形式
47 0
|
7月前
|
XML Java Maven
Spring中AOP最简单实例-XML形式
Spring中AOP最简单实例-XML形式
31 0
|
8月前
|
设计模式 Java 数据库连接
【Spring源码】JDBC数据源访问实现
我们再来看看阅读线索三,这方面我们从设计模式进行入手。阅读线索三:从这个模块可以学到什么我们看下以下代码,PreparedStatement实例的是由PreparedStatementCreator实现的。再来看看PreparedStatementCreator接口,一共有三个子类实现。也就是说PreparedStatement的三种不同实现被封装到三个子类中,而具体需要哪种实现,只需要传入不同。
【Spring源码】JDBC数据源访问实现
|
7月前
|
移动开发 Java Maven
基于OSGi的Virgo Server最简单Spring web实例
基于OSGi的Virgo Server最简单Spring web实例
87 0