spring读写分离

Posted smile_elims

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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读写分离 - 事务注解篇

spring 配置多数据源(mysql读写分离)

mysql读写分离

简单好用!利用Spring AOP技术10分钟实现一个读写分离方案

读写分离很难吗?Spring Boot 结合 aop 简单就实现了