用DynamicDataSource类辅助切换多数据源
实现AbstractRoutingDataSource接口,在类中定义
public static final String plateBaseDataSource= "plateBaseDataSource";
public static final String lgCommonDataSource= "lgCommonDataSource";
public static final String subApplicationDataSource= "subApplicationDataSource";
public static final ThreadLocal<String> contextHolder = new ThreadLocal<String>(){};
切换与清空数据缘方法为
public static void clearCustomerDataSource(){ contextHolder.remove(); } public static void setCustomerDataSource(String customerType){ contextHolder.set(customerType); }
对应配置文件中,数据源定义为
<bean id="plateBaseDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="${plateBase.driverClassName}" /> <property name="url" value="${plateBase.url}" /> <property name="username" value="${plateBase.uname}" /> <property name="password" value="${plateBase.password}" /> <!-- 连接池启动时的初始值 --> <property name="initialSize" value="${plateBase.initialSize}" /> <!-- 连接池的最大值 --> <property name="maxActive" value="${plateBase.maxActive}" /> <!-- 最大空闲值.当经过一个高峰时间后,连接池可以慢慢将已经用不到的连接慢慢释放一部分,一直减少到maxIdle为止 --> <property name="maxIdle" value="${plateBase.maxIdle}" /> <!-- 最小空闲值.当空闲的连接数少于阀值时,连接池就会预申请去一些连接,以免洪峰来时来不及申请 --> <property name="minIdle" value="${plateBase.minIdle}" /> <property name="validationQuery" value="select 1 from dual"></property> </bean> <bean id="lgCommonDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="${lgCommon.driverClassName}" /> <property name="url" value="${lgCommon.url}" /> <property name="username" value="${lgCommon.uname}" /> <property name="password" value="${lgCommon.password}" /> <!-- 连接池启动时的初始值 --> <property name="initialSize" value="${lgCommon.initialSize}" /> <!-- 连接池的最大值 --> <property name="maxActive" value="${lgCommon.maxActive}" /> <!-- 最大空闲值.当经过一个高峰时间后,连接池可以慢慢将已经用不到的连接慢慢释放一部分,一直减少到maxIdle为止 --> <property name="maxIdle" value="${lgCommon.maxIdle}" /> <!-- 最小空闲值.当空闲的连接数少于阀值时,连接池就会预申请去一些连接,以免洪峰来时来不及申请 --> <property name="minIdle" value="${lgCommon.minIdle}" /> <property name="validationQuery" value="select 1 from dual"></property> </bean>
定义DataSource为
<bean id="dataSource" class="heb.ysbs.utils.lgcommon.DynamicDataSource">
<property name="defaultTargetDataSource" ref="${defaultTargetDataSource}"/>
<property name="customDefaultDataSource" value="${defaultTargetDataSource}"/>
<property name="customLgBaseLogTableName" value="${customLgBaseLogTableName}"/>
<property name="targetDataSources" >
<map>
<entry key="plateBaseDataSource" value-ref="plateBaseDataSource"/>
<entry key="lgCommonDataSource" value-ref="lgCommonDataSource"/>
</map>
</property>
</bean>
jdbctemplate常规定义,没什么好讲
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource" />
</bean>
以上为数据源切换部分 ,这时切换数据源可直接调用DynamicDataSource.clearCustomerDataSource,在配置事务后,进入事务线程后jdbc得到默认DataSource,DynamicDataSource方法设置数据源在事务中执行的jdbc中不体现(线程问题,一知半解)
解决方法是在事务开启前切换数据源,用aop增强
定义工具类
<bean id="dataSourceExchange" class="fasp.utils.lgcommon.DataSourceExchange"></bean>
定义切片,排序在事务之前 :事务切点order=2,
<aop:config proxy-target-class="true">
<aop:pointcut id="dataSourcetransactionPointcut" expression="(execution(* fasp.service.lgcommon..*.*(..))) )" />
<aop:aspect id="aspect" ref="dataSourceExchange" order="1" >
<aop:before method="before" pointcut-ref="dataSourcetransactionPointcut" />
<aop:after method="after" pointcut-ref="dataSourcetransactionPointcut" />
</aop:aspect>
</aop:config>
个人习惯,感觉定义两个切点灵活,这里没有必要每个方法都进行数据切换如果也用 在一个aop:pointcut 定义两个aop:advisor就还要在拦截器中判断调用方法,其他资料中看到的
invoke方法
package com.lei.demo.aop.schema; import java.lang.reflect.Method; import org.aopalliance.intercept.MethodInterceptor; import org.aopalliance.intercept.MethodInvocation; public class HelloAroundAdvice implements MethodInterceptor { public Object invoke(MethodInvocation arg0) throws Throwable { System.out.println("++++++before advice"); arg0.proceed(); System.out.println("++++++after advice"); return null; } }
工具类DataSourceExchange中方法
1 /** 2 * 事务加载前执行 3 * 切换数据源 4 * @param call 5 */ 6 public void before(JoinPoint call){ 7 8 Object[] obj=call.getArgs();//参数集合 9 String dataSourceName=(String)(obj[0]);//规则:默认第一个参数为datasourcename 10 //Signature signature=call.getSignature(); //参数类型集合 11 // String [] argNames= ( (MethodSignature) signature ).getParameterNames();//参数名 12 DynamicDataSource.setCustomerDataSource( dataSourceName); 13 14 } 15 /** 16 * 事务加载前执行 17 * 清空数据源 18 * @param call 19 */ 20 public void after(JoinPoint call){ 21 DynamicDataSource.clearCustomerDataSource(); 22 //String parameter= DynamicDataSource.getCustomDefaultDataSource(); 23 //DynamicDataSource.setCustomerDataSource(parameter); 24 } 25 }
原文:https://www.cnblogs.com/Isolate/p/11714723.html