栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

基于Spring的aop实现多数据源动态切换

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

基于Spring的aop实现多数据源动态切换

Spring多数据源管理类AbstractRoutingDataSource

实现AbstractRoutingDataSource重写determineCurrentLookupKey

首先配置项目的多数据源实体类交给spring管理


        
	

	
	    
	    

		
		
		
		

		
		
		
		

		
		

		
		

		
		

		
		
		
		

		
	    
	

	
	
		
		

		
		
		
		

		
		
		
		

		
		

		
		

		
		

		
		
		
		
	

	
	
		
		
			
				
				
			
		
	

	

 在application.properties文件配置数据库参数

default.jdbc.type=
default.jdbc.driver=
default.jdbc.url=
default.jdbc.username=
default.jdbc.password=

default.jdbc.pool.init=1
default.jdbc.pool.minIdle=3
default.jdbc.pool.maxActive=20

default.jdbc.testSql=SELECt 'x' FROM DUAL


dds.jdbc.driver=
dds.jdbc.url=
dds.jdbc.username=
dds.jdbc.password=

数据源枚举类  DataSources

public enum DataSources {
    MASTER, SLAVE
}

自定义数据源管理类  DataSourceTypeManager

public class DataSourceTypeManager {
    //ThreadLocal一般称为线程本地变量,它是一种特殊的线程绑定机制,将变量与线程绑定在一起,为每一个线程维护一个独立的变量副本 ThreadLocal可以理解为将对象的作用范围限制在一个线程上下文中,使得变量的作用域为“线程级”
    private static final ThreadLocal dataSourceTypes = new ThreadLocal() {
        @Override
        protected DataSources initialValue() {
            return DataSources.MASTER;
        }
    };

    public static DataSources get() {
        return dataSourceTypes.get();
    }

    public static void set(DataSources dataSourceType) {
        dataSourceTypes.set(dataSourceType);
    }

    public static void reset() {
        dataSourceTypes.set(DataSources.MASTER);
    }
}
通过实现AbstractRoutingDataSource重写determineCurrentLookupKey切换数据源
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;


public class ThreadLocalRountingDataSource extends AbstractRoutingDataSource {
    @Override
    protected Object determineCurrentLookupKey() {
        return DataSourceTypeManager.get();
    }
}

最后,通过aop切面动态切换数据源,这里我用的注解的方式,其他的方法请自行百度

注解类 DataSource

import java.lang.annotation.*;

@documented
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface DataSource {
    // 这个配置了默认数据源SLAVE
    DataSources targetDataSurce() default DataSources.SLAVE;
}
根据aop动态修改数据源
@Aspect
@Component
@Order(1)
public class DataSourcesChange {
    private static final Logger logger = LoggerFactory.getLogger(DataSource.class);
    @Pointcut("@annotation(这里是上面注解的路径名)")
    public void point() {
    }

    @Before(value = "point()")
    public void before(JoinPoint jp) {
        Class targetClass = jp.getTarget().getClass();
        String methodName = jp.getSignature().getName(); //方法名称
        Class[] parameterTypes = ((MethodSignature)jp.getSignature()).getParameterTypes(); //方法参数类型列表
        logger.debug("========== "+targetClass.getName()+"."+methodName+" ==========");
        Method method=null;
        try {
            method = targetClass.getMethod(methodName, parameterTypes); //获取方法
        } catch (Exception e) {
            logger.error("========== sourceBefore get method error ==========" ,e);
        }
        if(method!=null && method.isAnnotationPresent(DataSource.class)){
            DataSource da = method.getAnnotation(DataSource.class);
            DataSources dataSurce = da.targetDataSurce();
            DataSourceTypeManager.set(dataSurce);
            logger.debug("========== 	set dataSource "+dataSurce+" ==========");
        }
    }

    @After(value = "point()")
    public void after(JoinPoint jp) {
        DataSourceTypeManager.set(DataSources.MASTER);
    }
}

之后只要在方法中添加注解

@DataSource(targetDataSurce = DataSources.SLAVE)就可以了

也可以使用@DataSource 等价于 @DataSource(targetDataSurce = DataSources.MASTER)

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/572347.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号