mysql主从复制(读写分离)java实现

代码中建议在service(业务)层进行主从分离。同一个service方法内部不建议再进行主从分离。这里是事务切面层,我们知道,在同一个事务中会使用同一条链接进行处理,在业务层方法内部逻辑不再建议进行主从分离,避免数据不一致问题的出现

以下方案通过 继承 AbstractRoutingDataSource类+注解+aop+ThreadLocal 实现注解方式的数据源的动态切换

 

1、读数据库切换注解类,在service注解表示开启读库操作,自动方法完成后自动清空数据源数据

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD,ElementType.TYPE})
@Inherited
public @interface SlaveDataSource {

}

2、spring aop切面类

@Aspect
public class DataSourceAspect {
    private static final Logger LOGGER = LoggerFactory.getLogger(DataSourceAspect.class);
    /**
     * 写库对应的数据源key 默认此库
     */
    public static final String MASTER = "master";

    /**
     * 读库对应的数据源key
     */
    public static final String SLAVE = "slave";

    /**
     * 在service层方法获取datasource对象之前,在切面中指定当前线程数据源slave
     */
    @Before(value = "execution(* *(..)) && @annotation(SlaveDataSource)")
    public void before(JoinPoint point) {
        String clazz = point.getTarget().getClass().getName();
        String name = point.getSignature().getName();
        LOGGER.debug(clazz+"."+name+" --- datasource---> :"+SLAVE);
        DataSourceHolder.putDataSource(SLAVE);
    }

    @After(value = "execution(* *(..)) && @annotation(SlaveDataSource)")
    public void after(JoinPoint joinPoint) {
        DataSourceHolder.clearDataSourceType();
    }

注意,需要开启springAop配置,同时将对象反向注入

 
    
    
    

3、动态数据源类,继承 org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;

public class DynamicDataSource extends AbstractRoutingDataSource {


    /**
     * 获取与数据源相关的key
     * 此key是Map resolvedDataSources 中与数据源绑定的key值
     * 在通过determineTargetDataSource获取目标数据源时使用
     */
    @Override
    protected Object determineCurrentLookupKey() {
        return DataSourceHolder.getDataSource();
    }

}

4、数据源处理类

public class DataSourceHolder {

    public static final ThreadLocal HOLDER = new ThreadLocal();

    /**
     * 绑定当前线程数据源
     */
    public static void putDataSource(String datasource) {
        HOLDER.set(datasource);
    }

    /**
     * 获取当前线程的数据源
     *
     * @return
     */
    public static String getDataSource() {
        return HOLDER.get();
    }

    /**
     * 移除数据源
     */
    public static void clearDataSourceType() {
        HOLDER.remove();
    }
}

springMybatis.xml的配置,注:使用的为阿里的druid数据库连接池,如果使用dbcp请自行切换


    
        
        
        
    
    
    
        
        
        
        
        

        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
            
                
            
        
        
    

    
    
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
            
                
            
        
        
    

    
    
        
            
                
                
                
                
            
        

        
    

使用方式:对service方法上添加注解切换数据源,默认为主库

@Service
public class PingServiceImpl implements PingService {


    private final BasicConfigDao basicConfigDao;

    @Autowired
    public PingServiceImpl(BasicConfigDao basicConfigDao) {
        this.basicConfigDao = basicConfigDao;
    }


    @Override
    public void pingMaster() {
        basicConfigDao.ping();
    }

    @SlaveDataSource
    @Override
    public void pingSalve() {
        basicConfigDao.ping();
    }

}

 

你可能感兴趣的:(数据库,读写分离,mysql,druid)