spring读写分离
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读写分离的更多相关文章
- [Spring] - 读写分离
使用Spring可以做到在应用层中实现数据库的读写分离. 参考文档: http://blog.csdn.net/lifuxiangcaohui/article/details/7280202 思路是使 ...
- spring读写分离(配置多数据源)[marked]
我们今天的主角是AbstractRoutingDataSource,在Spring2.0.1发布之后,引入了AbstractRoutingDataSource,使用该类可以实现普遍意义上的多数据源管理 ...
- 基于Spring读写分离
为什么是基于Spring的呢,因为实现方案基于Spring的事务以及AbstractRoutingDataSource(spring中的一个基础类,可以在其中放多个数据源,然后根据一些规则来确定当前需 ...
- springboot读写分离--temp
我最初的想法是: 读方法走读库,写方法走写库(一般是主库),保证在Spring提交事务之前确定数据源. 保证在Spring提交事务之前确定数据源,这个简单,利用AOP写个切换数据源的切面,让他的优先级 ...
- Spring aop应用之实现数据库读写分离
Spring加Mybatis实现MySQL数据库主从读写分离 ,实现的原理是配置了多套数据源,相应的sqlsessionfactory,transactionmanager和事务代理各配置了一套,如果 ...
- Spring 实现数据库读写分离
随着互联网的大型网站系统访问量的增高,数据库访问压力方面不断的显现而出,所以许多公司在数据库层面采用读写分离技术,也就是一个master,多个slave.master负责数据的实时更新或实时查询,而s ...
- 从零开始学 Java - Spring AOP 实现主从读写分离
深刻讨论为什么要读写分离? 为了服务器承载更多的用户?提升了网站的响应速度?分摊数据库服务器的压力?就是为了双机热备又不想浪费备份服务器?上面这些回答,我认为都不是错误的,但也都不是完全正确的.「读写 ...
- 基于spring的aop实现读写分离与事务配置
项目开发中经常会遇到读写分离等多数据源配置的需求,在Java项目中可以通过Spring AOP来实现多数据源的切换. 一.Spring事务开启流程 Spring中通常通过@Transactional来 ...
- spring MVC、mybatis配置读写分离
spring MVC.mybatis配置读写分离 1.环境: 3台数据库机器,一个master,二台slave,分别为slave1,slave2 2.要实现的目标: ①使数据写入到master ②读数 ...
随机推荐
- HttpContext.Cache 详解
提到HttpContext.Cache必然会想到Application,他们有什么共性和不同点呢,我们一一道来 相同点: 1.两者都是使用键值对来存储对象 2.两者都是应用程序同生命周期(在cache ...
- Android Studio下SQLite数据库的配置与使用(完)
一,AS开发app用,所用的数据库有限制,必须使用较小的SQLite(MySql和Sql Server想想就不显示) 但是该数据库并不需要我们单独下载,安装的SDK中已经有了,在C:\AndroidS ...
- MySQL日期 字符串 时间戳互转
平时比较常用的时间.字符串.时间戳之间的互相转换,虽然常用但是几乎每次使用时候都喜欢去搜索一下用法:本文将作为一个笔记,整理一下三者之间的 转换(即:date转字符串.date转时间戳.字符串转dat ...
- 上载android应用的apk文件变成了zip-网下转载的解决方案
下载android应用的apk文件变成了zip--网上转载的解决方案 下载android应用的apk文件变成了zip--网上转载的解决方案 解决方案一. 最近把开发的android应用放在公司网站上, ...
- windows下安装RabbitMq-Service
一.RaibbitMQ服务器配置 1. 准备工作.如果之前安装过RabbitMQ软件,若想重新安装,必须先把之前的RabbitMQ相关软件卸载. 2. 安装ERLANG语言包.首先到http://ww ...
- zoj3551 Bloodsucker ——概率DP
Link: http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=4530 A[i]数组表示当吸血鬼有 I 个的时候,还需要的天数.可以 ...
- codeforces298c
link:http://codeforces.com/problemset/problem/298/C 这道题目可以看出来我智商确实拙计 #include <iostream> #incl ...
- SSD(Single Shot MultiBox Detector)的安装配置和运行
下文图文介绍转自watersink的博文SSD(Single Shot MultiBox Detector)不得不说的那些事. 该方法出自2016年的一篇ECCV的oral paper,SSD: Si ...
- Streaming replication slots in PostgreSQL 9.4
Streaming replication slots are a pending feature in PostgreSQL 9.4, as part of the logical changese ...
- 分布式id 实现方式
1. uuid 2. twitter的Snowflake 3. MongoDB ObjectID 4. Ticket Server 5. Instagram采用的方式(UUID方式)