使用AOP 实现多数据源 切换
多数据源的实现,这里就来个实例吧
1、在 spring 的配置文件中数据源信息
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:util="http://www.springframework.org/schema/util" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-4.1.xsd http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-4.1.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.1.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.1.xsd"> <!-- 加载配置属性文件 --> <context:property-placeholder ignore-unresolvable="true" location="classpath:conf.properties" /> <!-- C3P0连接池配置 --> <bean id="dataSource_zh_CN" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="${db1.jdbc.driver}" /> <property name="jdbcUrl" value="${db1.jdbc.url}" /> <property name="user" value="${db1.jdbc.username}" /> <property name="password" value="${db1.jdbc.password}" /> <!-- 配置初始化大小、最小、最大 --> <property name="initialPoolSize" value="${jdbc.pool.init}" /> <property name="minPoolSize" value="${jdbc.pool.minIdle}" /> <property name="maxPoolSize" value="${jdbc.pool.maxActive}" /> <property name="maxIdleTime" value="60000" /> </bean> <!-- C3P0连接池配置 --> <bean id="dataSource_en_US" class="com.mchange.v2.c3p0.ComboPooledDataSource"> <property name="driverClass" value="${db2.jdbc.driver}" /> <property name="jdbcUrl" value="${db2.jdbc.url}" /> <property name="user" value="${db2.jdbc.username}" /> <property name="password" value="${db2.jdbc.password}" /> <!-- 配置初始化大小、最小、最大 --> <property name="initialPoolSize" value="${jdbc.pool.init}" /> <property name="minPoolSize" value="${jdbc.pool.minIdle}" /> <property name="maxPoolSize" value="${jdbc.pool.maxActive}" /> <property name="maxIdleTime" value="60000" /> </bean> <bean id="dataSource" class="com.bkc.bpmp.core.datasource.DynamicDataSource"> <property name="targetDataSources"> <map key-type="java.lang.String"> <entry key="dataSource_zh_CN" value-ref="dataSource_zh_CN" /> <entry key="dataSource_en_US" value-ref="dataSource_en_US" /> </map> </property> <property name="defaultTargetDataSource" ref="dataSource_zh_CN" /> </bean> </beans>
2、在 Spring 配置文件中配置 AOP 切面信息,当访问 包 com.bkc.bpmp 及下面的子包中的类的方法时
<!-- 开启aop注解方式 --> <aop:aspectj-autoproxy proxy-target-class="false"/> <bean id="dataSourceInterceptor" class="com.bkc.bpmp.core.aspectj.DataSourceInterceptor" /> <aop:config> <aop:aspect id="dataSourceAspect" ref="dataSourceInterceptor"> <aop:pointcut id="setDs" expression="execution(* com.bkc.bpmp..*.*(..))" /> <aop:before method="setdataSourceCnOrEn" pointcut-ref="setDs"/> </aop:aspect> </aop:config>
3、实现 数据源 切面切换的方法,这里假设是根据 locale 来切换数据源的
package com.bkc.bpmp.core.aspectj; import java.lang.reflect.Method; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.reflect.MethodSignature; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.context.i18n.LocaleContextHolder; import com.bkc.bpmp.core.annotation.DbType; import com.bkc.bpmp.core.contants.DbTypeEnum; import com.bkc.bpmp.core.datasource.DatabaseContextHolder; /** * 用于实现 动态数据库切换的AOP 方法类 * * @author ppnie */ public class DataSourceInterceptor { /** * 设置数据源为中文 还是 英文 * @param jp */ public void setdataSourceCnOrEn(JoinPoint jp) { String curLocale = LocaleContextHolder.getLocale().toString(); System.out.println("==================dataSource_"+curLocale); if(curLocale.equals("en_US")) { DatabaseContextHolder.setCustomerType("dataSource_"+curLocale); } else { DatabaseContextHolder.setCustomerType("dataSource_zh_CN"); } logger.info("======="+"dataSource_"+curLocale+"======="); } }
4、自定义动态数据源的切换方法,主要就是 写一个 AbstractRoutingDataSource 的子类啦
package com.bkc.bpmp.core.datasource; public class DatabaseContextHolder { private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>(); public static void setCustomerType(String customerType) { contextHolder.set(customerType); } public static String getCustomerType() { return contextHolder.get(); } public static void clearCustomerType() { contextHolder.remove(); } }
package com.bkc.bpmp.core.datasource; import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource; public class DynamicDataSource extends AbstractRoutingDataSource { @Override protected Object determineCurrentLookupKey() { return DatabaseContextHolder.getCustomerType(); } }
就这样,达到触发条件的时候,就会去切换数据库啦
作者:panie
出处:http://www.cnblogs.com/panie2015/
如果您希望与我交流互动,欢迎加我微信
本文内容为作者辛苦整理书写,欢迎转载,但请保留文章出处