**涉及公司机密一些敏感点不易露出,如有交流或不懂请加本人QQ:787753924
个人劳动成果,转载请注明出处:http://blog.csdn.net/hr787753/article/details/76528301**
前段时间所做的工作涉及到两个不同的服务器不同的数据库之间的数据的导入,所以用到了多数据源的切换,这里的数据源切换是通过AOP 将Mapper(持久层)层切开,针对这个切入点生成代理对象,在前置通知里面为目标方法赋予数据库的连接属性,废话不多说,首先说几个要用到的知识点:
1.org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource
Spring会在获取数据源时自动调用 此类详情请看Spring源码
创建一个类DynamicDataSource继承他,并实现重写方法 在重写方法中
返回3得到得本地线程中的值
2.自定义一个注解@DataSource ,设置此注解运行在类和方法上 并为运行时注解
添加一个String value();
3.创建一个类DBContextHolder ,其中用到了本地线程变量ThreadLocal保证线程安全
//只读库
public static final String DATA_SOURCE_BASE = "base"; // 对应dataSourceBase数据源key
//写入库
public static final String DATA_SOURCE_SLAVE = "slave"; // 对应远程dataSourceSlave数据源key
private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>();
/**
* 设置数据源
*
* @param dbType
* 本类中两个静态变量的值
*/
public static void setDBType(String dbType) {
contextHolder.set(dbType);
}
public static String getDBType() {
return contextHolder.get();
}
public static void clearDBType() {
contextHolder.remove();
}
4.创建一个切面DataSourceAspect 创建前置通知
在前置通知中开始对目标方法执行操作 ,具体操作为:获取当前目标方法所在的类上的(接口上的) 或者方法上的注解的value值
获取完value值后将此value值(Base或者Slave)设置给本地线程变量
5.Spring配置文件中 配置双数据源
之后设置 数据源池:
<bean id="dataSource" class="cn.tarena.ht.aspect.DynamicDataSource">
<property name="targetDataSources">
<map>
<entry key="base" value-ref="dataSourceBase"></entry>
<entry key="slave" value-ref="dataSourceSlave"></entry>
</map>
</property>
<property name="defaultTargetDataSource" ref="dataSourceBase" />
</bean>
配置文件中配置AOP 对Mapper进行横切
<bean id="dataSourceAspect" class="cn.tarena.ht.aspect.DataSourceAspect"></bean>
<!-- 配置切面 -->
<aop:config>
<aop:pointcut expression="execution(* cn.tarena.ht.mapper.*.*(..))" id="pc"/>
<aop:aspect ref="dataSourceAspect">
<aop:before method="intercept" pointcut-ref="pc"/>
</aop:aspect>
</aop:config>