1.配置两个数据源到动态数据源
<bean id="dataSource" class="com.che.rw.datasource.DynamicDataSource"> <property name="defaultTargetDataSource" ref="masterDataSource"></property> <property name="targetDataSources"> <map> <entry key="master" value-ref="masterDataSource"></entry> <entry key="slave" value-ref="slaveDataSource"></entry> </map> </property> </bean>
<!-- 数据源切面 --> <bean id="dualDataSourceAspect" class="com.che.rw.aspect.DataSourceAspect"> <property name="slaveList"> <list> <value>query</value> <value>get</value> <value>find</value> <value>select</value> </list> </property> <property name="logEnable" value="false" /> </bean>
//aop 配置拦截多个mapper 包
<!-- 配置aop --> <aop:config> <!-- <aop:pointcut id="pointcut1" expression="execution(* com.sfbm.carmall.service.*.*(..))" /> --> <!-- <aop:pointcut id="pointcut2" expression="execution(* com.che.mall..service.*.*(..))" /> --> <aop:pointcut id="pointcut1" expression="execution(* com.sfbm.carmall..*Service.*(..))" /> <aop:pointcut id="pointcut2" expression="execution(* com.che.mall..*Service.*(..))" /> <aop:aspect id="aspect1" ref="dualDataSourceAspect"> <aop:before pointcut-ref="pointcut1" method="before" /> </aop:aspect> <aop:aspect id="aspect2" ref="dualDataSourceAspect"> <aop:before pointcut-ref="pointcut2" method="before" /> </aop:aspect> </aop:config>
2.sessionFactory 和 Transactionmanager 设置为动态数据源
3.定义注解
@Retention(RetentionPolicy.RUNTIME) @Target({ElementType.METHOD}) public @interface Master { }
@Retention(RetentionPolicy.RUNTIME) @Target({ElementType.METHOD}) public @interface Slave { }public class DynamicDataSource extends AbstractRoutingDataSource { public DynamicDataSource() { } protected Object determineCurrentLookupKey() { return DynamicDataSourceHolder.getDataSouce(); } }
public class DynamicDataSourceHolder { private static final ThreadLocal<String> holder = new ThreadLocal(); public DynamicDataSourceHolder() { } public static void putDataSource(String name) { holder.set(name); } public static String getDataSouce() { return (String)holder.get(); } }
public class DataSourceAspect { private List<String> slaveList; private boolean logEnable = false; public DataSourceAspect() { } public void before(JoinPoint point) { try { Object e = point.getTarget(); String method = point.getSignature().getName(); Class clazz = e.getClass(); Class[] parameterTypes = ((MethodSignature)point.getSignature()).getMethod().getParameterTypes(); Method m = clazz.getMethod(method, parameterTypes); if(m == null) { return; } String dataSourceName = "master"; if(m.isAnnotationPresent(Master.class)) { dataSourceName = "master"; } else if(m.isAnnotationPresent(Slave.class)) { dataSourceName = "slave"; } else if(this.slaveList != null && !this.slaveList.isEmpty()) { String mName = m.getName(); Iterator i$ = this.slaveList.iterator(); while(i$.hasNext()) { String start = (String)i$.next(); if(mName.startsWith(start)) { dataSourceName = "slave"; break; } } } DynamicDataSourceHolder.putDataSource(dataSourceName); if(this.logEnable) { System.out.println(dataSourceName); } } catch (Exception var11) { var11.printStackTrace(); } } public void setSlaveList(List<String> slaveList) { this.slaveList = slaveList; } public void setLogEnable(boolean logEnable) { this.logEnable = logEnable; } }
3.配置spring aop ,扫描的包为mybatis mapper 文件路径 在mapper方法执行之前 执行前置通知,动态切换数据源