从零开始学Java-SpringAOP实现主从读写分离publicclassJdbcContextHolder{
privatestaticfinalThreadLocalcontextHolder=newThreadLocal();
publicstaticvoidsetJdbcType(StringjdbcType){
contextHolder.set(jdbcType);
}
publicstaticvoidsetSlave(){
setJdbcType("slave");
}
publicstaticvoidsetMaster(){
clearJdbcType();
}
publicstaticStringgetJdbcType(){
return(String)contextHolder.get();
}
publicstaticvoidclearJdbcType(){
contextHolder.remove();
}
}
这个类的作用就是用来设置、获取数据源连接
二、新建DynamicDataSource.java类,继承于AbstractRoutingDataSource
importorg.springframework.jdbc.www.visa158.com.datasource.lookup.AbstractRoutingDataSource;
importcn.mayongfa.common.JdbcContextHolder;
publicclassDynamicDataSourceextendsAbstractRoutingDataSource{
@Override
protectedObjectdetermineCurrentLookupKey(){
//获取当前数据源连接
returnJdbcContextHolder.getJdbcType();
}
}
通过研究,我们知道determineCurrentLookupKey方法是获取相关数据源连接的,所以重写determineCurrentLookupKey方法就可以啦,然后我们去通过刚刚我们建立的JdbcContextHolder类去获取。那怎么设置呢?
三、建立数据源DataSourceType.java枚举类
publicenumDataSourceType{
//主库
Master("master"),
//从库
Slave("slave");
privateDataSourceType(Stringname){
this.name=name;
}
privateStringname;
publicStringgetName(){
returnname;
}
publicvoidsetName(Stringname){
this.name=name;
}
}
这个枚举类的作用其实就是为了设置数据源而生的,它的目的就是让设置数据源时更方便,如丝般顺滑。
四、新建DataSource.javaAnnotation(自定义注解)类
importjava.lang.annotation.Documented;
importjava.lang.annotation.ElementType;
importjava.lang.annotation.Retention;
importjava.lang.annotation.RetentionPolicy;
importjava.lang.annotation.Target;
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
public@interfaceDataSource{
DataSourceTypevalue(www.visa158.com)defaultDataSourceType.Master;
}
自定义注解的意义不再过多讨论,一句话来说就是可以让你在类或方法名上以打标签的形式让该方法变得不一样。具体怎么「不一样」,这个在于你。
五、新建DataSourceChoose.java数据库切换类
importjava.lang.reflect.Method;
importorg.aspectj.lang.JoinPoint;
importorg.aspectj.lang.reflect.MethodSignature;
importcn.mayongfa.common.JdbcContextHolder;
publicclassDataSourceChoose{
//方法执行前
publicvoidbefore(JoinPointpoint){
Objecttarget=point.getTarget();
Stringmethod=point.getSignature().getName();
Class>[]classz=target.getClass().getInterfaces();
MethodSignaturemethodSignature=(MethodSignature)point.getSignature();
Class>[]parameterTypes=methodSignature.getMethod().getParameterTypes();
try{
Methodm=classz[0].getMethod(method,parameterTypes);
if(m!=null&&m.isAnnotationPresent(DataSource.class)){
DataSourcedata=m.getAnnotation(DataSource.class);
JdbcContextHolder.clearJdbcType();
JdbcContextHolder.setJdbcType(data.value().getName());
}
}catch(Exceptione){
//TODO:handleexception
}
}
}
这个其实是一个拦截器类,主要作用就是拦截那些方法名上有@DataSource这个自定义注解的,完了根据获取注解的value()值,来做相应的数据源切换。
到这里,整个读写分离的分析及业务逻辑和具体代码都完了
|
|