import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

public class ChooseDataSource extends AbstractRoutingDataSource {

	@Override
protected Object determineCurrentLookupKey() {
return HandleDataSource.getDataSource();
} }

  

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; /**
* RUNTIME 编译器将把注释记录在类文件中,在运行时 VM 将保留注释,因此可以反射性地读取。
*
* @author yangGuang
*
*/ @Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface DataSource {
String value();
}
import java.lang.reflect.Method;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.reflect.MethodSignature; public class DataSourceAspect { /**
* 拦截目标方法,获取由@DataSource指定的数据源标识,设置到线程存储中以便切换数据源
*
* @param point
* @throws Exception
*/
public void intercept(JoinPoint point) throws Exception {
Class<?> target = point.getTarget().getClass();
MethodSignature signature = (MethodSignature) point.getSignature();
// 默认使用目标类型的注解,如果没有则使用其实现接口的注解
for (Class<?> clazz : target.getInterfaces()) {
resolveDataSource(clazz, signature.getMethod());
}
resolveDataSource(target, signature.getMethod());
} /**
* 提取目标对象方法注解和类型注解中的数据源标识
*
* @param clazz
* @param method
*/
private void resolveDataSource(Class<?> clazz, Method method) {
try {
Class<?>[] types = method.getParameterTypes();
// 默认使用类型注解
if (clazz.isAnnotationPresent(DataSource.class)) {
DataSource source = clazz.getAnnotation(DataSource.class);
HandleDataSource.putDataSource(source.value());
}
// 方法注解可以覆盖类型注解
Method m = clazz.getMethod(method.getName(), types);
if (m != null && m.isAnnotationPresent(DataSource.class)) {
DataSource source = m.getAnnotation(DataSource.class);
HandleDataSource.putDataSource(source.value());
}
} catch (Exception e) {
// System.out.println(clazz + ":" + e.getMessage());
}
} }
public class HandleDataSource {
public static final ThreadLocal<String> holder = new ThreadLocal<String>(); public static void putDataSource(String datasource) {
holder.set(datasource);
} public static String getDataSource() {
return holder.get();
} public static void clearDataSource() {
holder.remove();
} }

spring配置文件

<bean id="dataSource" class="hometree.ecs.business.db.dao.util.ChooseDataSource">
<property name="targetDataSources">
<map key-type="java.lang.String">
<!-- write -->
<entry key="write" value-ref="writeDataSource"/>
<!-- read -->
<entry key="read" value-ref="readDataSource"/>
<!-- 读写 -->
<entry key="wr" value-ref="dataSourceAdmin"/>
</map> </property>
<!-- 默认 -->
<property name="defaultTargetDataSource" ref="dataSourceAdmin"/>
</bean> <!-- 激活自动代理功能 -->
<aop:aspectj-autoproxy proxy-target-class="true"/>
<!-- 配置数据库注解aop -->
<bean id="dataSourceAspect" class="aa.dd.cc.DataSourceAspect" />
<aop:config>
<aop:aspect id="c" ref="dataSourceAspect">
<!--扫描下边的所有方法都要过before -->
<aop:pointcut id="tx" expression="execution(* aa.dd.cc.*.*(..))"/>
<aop:before pointcut-ref="tx" method="intercept"/> <!-- intercept是执行的方法 -->
</aop:aspect>
</aop:config>
<!-- 配置数据库注解aop -->

在方法调用上:

@DataSource("read")//read与

 <entry key="read" value-ref="readDataSource"/>  对应

public void add(){

}

spring读写分离的更多相关文章

  1. [Spring] - 读写分离

    使用Spring可以做到在应用层中实现数据库的读写分离. 参考文档: http://blog.csdn.net/lifuxiangcaohui/article/details/7280202 思路是使 ...

  2. spring读写分离(配置多数据源)[marked]

    我们今天的主角是AbstractRoutingDataSource,在Spring2.0.1发布之后,引入了AbstractRoutingDataSource,使用该类可以实现普遍意义上的多数据源管理 ...

  3. 基于Spring读写分离

    为什么是基于Spring的呢,因为实现方案基于Spring的事务以及AbstractRoutingDataSource(spring中的一个基础类,可以在其中放多个数据源,然后根据一些规则来确定当前需 ...

  4. springboot读写分离--temp

    我最初的想法是: 读方法走读库,写方法走写库(一般是主库),保证在Spring提交事务之前确定数据源. 保证在Spring提交事务之前确定数据源,这个简单,利用AOP写个切换数据源的切面,让他的优先级 ...

  5. Spring aop应用之实现数据库读写分离

    Spring加Mybatis实现MySQL数据库主从读写分离 ,实现的原理是配置了多套数据源,相应的sqlsessionfactory,transactionmanager和事务代理各配置了一套,如果 ...

  6. Spring 实现数据库读写分离

    随着互联网的大型网站系统访问量的增高,数据库访问压力方面不断的显现而出,所以许多公司在数据库层面采用读写分离技术,也就是一个master,多个slave.master负责数据的实时更新或实时查询,而s ...

  7. 从零开始学 Java - Spring AOP 实现主从读写分离

    深刻讨论为什么要读写分离? 为了服务器承载更多的用户?提升了网站的响应速度?分摊数据库服务器的压力?就是为了双机热备又不想浪费备份服务器?上面这些回答,我认为都不是错误的,但也都不是完全正确的.「读写 ...

  8. 基于spring的aop实现读写分离与事务配置

    项目开发中经常会遇到读写分离等多数据源配置的需求,在Java项目中可以通过Spring AOP来实现多数据源的切换. 一.Spring事务开启流程 Spring中通常通过@Transactional来 ...

  9. spring MVC、mybatis配置读写分离

    spring MVC.mybatis配置读写分离 1.环境: 3台数据库机器,一个master,二台slave,分别为slave1,slave2 2.要实现的目标: ①使数据写入到master ②读数 ...

随机推荐

  1. C#之属性

    在C#类中有属性这个成员,C#属性用来读写类的字段.实际上是通过get和set访问器实现的.

  2. Flex文件结构

    一.文件.目录及其作用.project:描述工程信息,如 本工程名称.工程注释.相关工程信息.编译参数等 .flexProperties:记录与Flex本身相关的信息 .actionScriptPro ...

  3. HDU2222

    http://acm.hdu.edu.cn/showproblem.php?pid=2222 注意: 1. keyword可以相同,因此计算时要累计:cur->num++. 2. 同一个keyw ...

  4. Mark一下,一上午就这么过去了,关于客户端连接oracle10G的问题

    Mark一下,一上午就这么过去了,关于客户端连接oracle10G的问题 正常的客户端PLSQL和Navicat都可以正常连接Oracle(局域网内),但代码生成器和VS2015死活连不上,在网上找了 ...

  5. 【技术无关】GPS转北斗卫星定位 系统调研

    前言 陆地交通运输是当前GPS卫星定位系统最大的应用领域,我省自08年实施卫星定位系统建设以来,在车辆监控和调度方面发挥了突出的作用:主要功能包括车辆跟踪.线路规划和导航.信息查询.交通指挥.紧急援助 ...

  6. mac地址泛洪攻击的实验报告

    案例介绍: PC A 访问 本网络的一台FTPserver主机,中间人进行arp的投毒,获取PC-A和FTPserve之间的回话记录,截获用户名和密码. 实验拓扑:

  7. linux系统io的copy

    #include<stdio.h> #include<sys/types.h> #include<sys/stat.h> #include<fcntl.h&g ...

  8. firefox 不识别background-position-y / background-position-x

    火狐不识别background-position-y 或background-position-x; 案例: 页面: 背景图: 一列按钮,点击时让当前背景图的background-position-y ...

  9. div滚动条弹出层效果 (所需要的css文件和js文件,都已经上传到文件里面了progressbar.rar)

    <%--总的弹出层--%> <div class="tcck" id="joinclub" style="display:none& ...

  10. StringMisc

    //StringMisc.java // This program demonstrates the length, charAt and getChars // methods of the Str ...