上一篇文章实现了mysql的主从同步,所试着在springmcv中实现读写分离。
主要方式其实就是通过spingAop控制方法访问的数据库表,
由于我是基于前几文章的项目来实现的,所以项目搭建和jar都已经有了直接开始写实现,
第一步:sping配置文件
1,多数据源配置:
配置了两个一个读一个写:所以beanName分别为:readDataSource和writeDataSource数据源的ip分别为mysql主从的ip;
dataSource bean是自己用aop的方式写路由控制器,负责通过不同的key加载不同的数据源给最终调用数据库表操作的方法。
这个dataSource 最终的事物控制还是由
来控制,和一般的事物没什么却别;
现在看看路由的实现:
package com.java.spring.util.aspect;
import java.lang.reflect.Method;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import com.java.spring.util.dynamicDataSource.DataSource;
import com.java.spring.util.dynamicDataSource.DynamicDataSourceHolder;
/**
* @author 作者:zhaofq
* @version 创建时间:2017年4月14日 下午4:24:36
* 类说明:在访问每个方法之前会进行拦截调用,其目的就是通过方法调用key来加载不同的数据源
*/
public class DataSourceAspect {
//@Pointcut("execution(* com.apc.cms.service.*.*(..))")
public void pointCut(){};
// @Before(value = "pointCut()")
public void before(JoinPoint point)
{
Object target = point.getTarget();
System.out.println(target.toString());
String method = point.getSignature().getName();
System.out.println(method);
Class<?>[] classz = target.getClass().getInterfaces();
Class<?>[] parameterTypes = ((MethodSignature) point.getSignature())
.getMethod().getParameterTypes();
try {
Method m = classz[0].getMethod(method, parameterTypes);
System.out.println(m.getName());
if (m != null && m.isAnnotationPresent(DataSource.class)) {
DataSource data = m.getAnnotation(DataSource.class);
//加载已经在内存中数据源,
DynamicDataSourceHolder.putDataSource(data.value());
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
package com.java.spring.util.dynamicDataSource;
/**
* @author 作者:zhaofq
* @version 创建时间:2017年4月14日 下午4:22:41
* 类说明
*/
public class DynamicDataSourceHolder {
public static final ThreadLocal<String> holder = new ThreadLocal<String>();
public static void putDataSource(String name) {
holder.set(name);
}
public static String getDataSouce() {
return holder.get();
}
}
package com.java.spring.util.dynamicDataSource;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* @author 作者:zhaofq
* @version 创建时间:2017年4月14日 下午4:10:00
* 类说明
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface DataSource {
String value();
}
package com.java.spring.util.dynamicDataSource;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
/**
* @author 作者:zhaofq
* @version 创建时间:2017年4月14日 下午4:21:59
* 类说明
*/
public class DynamicDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
return DynamicDataSourceHolder.getDataSouce();
}
}
对应的几个类,完成实现,、
调用的方式:已经控制到了业务从sping配置就能找到
所只需要在操作数据方式的时候注解就可以: